API Implement back end for saving forms via react

This commit is contained in:
Damian Mooyman 2016-04-19 14:35:31 +12:00 committed by Ingo Schommer
parent ddfe660f0a
commit e2afcd0acb
6 changed files with 71 additions and 33 deletions

View File

@ -119,7 +119,6 @@ export class FormBuilderComponent extends SilverStripeComponent {
if (typeof formSchema.id !== 'undefined') {
const defaultData = {
ID: formSchema.schema.id,
SecurityID: this.props.config.SecurityID,
};

View File

@ -20,7 +20,7 @@ class HiddenField extends SilverStripeComponent {
getInputProps() {
return {
className: ['hidden', this.props.extraClass].join(' '),
id: this.props.name,
id: this.props.id,
name: this.props.name,
onChange: this.props.onChange,
type: 'hidden',
@ -42,7 +42,7 @@ HiddenField.propTypes = {
extraClass: React.PropTypes.string,
name: React.PropTypes.string.isRequired,
onChange: React.PropTypes.func,
value: React.PropTypes.string,
value: React.PropTypes.any,
};
export default HiddenField;

View File

@ -84,6 +84,9 @@ class Backend {
* endpoint({one: 1, two: 2, three: 3});
* // Calls http://example.org/1/2?three=3 with a HTTP body of '{"two": 2}'
* ```
*
* Custom HTTP headers can be passed to the second parameter of the endpoint
*
* **urlReplacement**
*
* Can be used to replace template placeholders in the 'url' endpoint spec.
@ -274,11 +277,11 @@ class Backend {
}
);
return (data = {}) => {
const headers = {
return (data = {}, headers = {}) => {
const mergedHeaders = Object.assign({}, headers, {
Accept: refinedSpec.responseFormat,
'Content-Type': refinedSpec.payloadFormat,
};
});
const mergedData = merge.recursive({}, refinedSpec.defaultData, data);
@ -302,8 +305,8 @@ class Backend {
);
const args = refinedSpec.method.toLowerCase() === 'get'
? [url, headers]
: [url, encodedData, headers];
? [url, mergedHeaders]
: [url, encodedData, mergedHeaders];
return this[refinedSpec.method.toLowerCase()](...args)
.then(parseResponse);

View File

@ -62,7 +62,7 @@ export function submitForm(submitApi, formId, fieldValues) {
payload: {},
});
submitApi(Object.assign({ ID: formId }, fieldValues))
submitApi(Object.assign({ ID: formId }, fieldValues), { 'X-Formschema-Request': 'state' })
.then(() => {
dispatch({
type: ACTION_TYPES.SUBMIT_FORM_SUCCESS,

View File

@ -25,12 +25,13 @@ class CampaignAdmin extends LeftAndMain implements PermissionProvider {
private static $menu_title = 'Campaigns';
private static $tree_class = 'ChangeSet';
private static $url_handlers = [
'GET sets' => 'readCampaigns',
'POST set/$ID/publish' => 'publishCampaign',
'POST set/$ID' => 'createCampaign',
'GET set/$ID/$Name' => 'readCampaign',
'POST $ID' => 'updateCampaign',
'DELETE set/$ID' => 'deleteCampaign',
];
@ -367,25 +368,6 @@ JSON;
}
}
/**
* REST endpoint to update a campaign.
*
* @param SS_HTTPRequest $request
*
* @return SS_HTTPResponse
*/
public function updateCampaign(SS_HTTPRequest $request) {
$id = $request->param('ID');
$response = new SS_HTTPResponse();
$response->addHeader('Content-Type', 'application/json');
$response->setBody(Convert::raw2json(['campaign' => 'update']));
// TODO Implement data update and permission checks
return $response;
}
/**
* REST endpoint to delete a campaign.
*
@ -460,20 +442,51 @@ JSON;
))->addHeader('Content-Type', 'application/json');
}
/**
* Url handler for edit form
*
* @param SS_HTTPRequest $request
* @return Form
*/
public function DetailEditForm($request) {
// Get ID either from posted back value, or url parameter
$id = $request->param('ID') ?: $request->postVar('ID');
return $this->getDetailEditForm($id);
}
/**
* @todo Use GridFieldDetailForm once it can handle structured data and form schemas
*
* @param int $id
* @return Form
*/
public function getDetailEditForm($id) {
return Form::create(
// Get record-specific fields
$record = null;
if($id) {
$record = ChangeSet::get()->byId($id);
}
if(!$record) {
$record = ChangeSet::singleton();
}
$fields = $record->getCMSFields();
// Add standard fields
$fields->push(HiddenField::create('ID'));
$form = Form::create(
$this,
'DetailEditForm',
ChangeSet::get()->byId($id)->getCMSFields(),
$fields,
FieldList::create(
FormAction::create('save', 'Save')
)
);
// Configure form to respond to validation errors with form schema
// if requested via react.
$form->setValidationResponseCallback(function() use ($form) {
return $this->getSchemaResponse($form);
});
return $form;
}
/**

View File

@ -267,6 +267,24 @@ class LeftAndMain extends Controller implements PermissionProvider {
return $response;
}
/**
* Given a form, generate a response containing the requested form
* schema if X-Formschema-Request header is set.
*
* @param Form $form
* @return SS_HTTPResponse
*/
protected function getSchemaResponse($form) {
$request = $this->getRequest();
if($request->getHeader('X-Formschema-Request')) {
$data = $this->getSchemaForForm($form);
$response = new SS_HTTPResponse(Convert::raw2json($data));
$response->addHeader('Content-Type', 'application/json');
return $response;
}
return null;
}
/**
* Returns a representation of the provided {@link Form} as structured data,
* based on the request data.
@ -1137,6 +1155,10 @@ class LeftAndMain extends Controller implements PermissionProvider {
/**
* Save handler
*
* @param array $data
* @param Form $form
* @return SS_HTTPResponse
*/
public function save($data, $form) {
$request = $this->getRequest();
@ -1159,9 +1181,9 @@ class LeftAndMain extends Controller implements PermissionProvider {
$this->extend('onAfterSave', $record);
$this->setCurrentPageID($record->ID);
$this->getResponse()->addHeader('X-Status', rawurlencode(_t('LeftAndMain.SAVEDUP', 'Saved.')));
$message = _t('LeftAndMain.SAVEDUP', 'Saved.');
if($request->getHeader('X-Formschema-Request')) {
$form->setMessage($message, 'good');
$data = $this->getSchemaForForm($form);
$response = new SS_HTTPResponse(Convert::raw2json($data));
$response->addHeader('Content-Type', 'application/json');
@ -1169,6 +1191,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
$response = $this->getResponseNegotiator()->respond($request);
}
$response->addHeader('X-Status', rawurlencode($message));
return $response;
}