Consistently set 'id' in FormSchema

The URL to request the schema representation is the unique identifier.
We can't default to $request->getURL() since that's different for form submissions.

The schema.schema_url key is redundant, since the identifier is already contained on the top level 'id' key.
Keeping schema_url in a schema itself makes it less portable, particularly once we transition into
generic schemas which are not reliant on a particular record context (that's only contained in the schema_url)

This also fixes the issue of form schemas not refreshing after submit,
e.g. when form fields are added or removed.
This commit is contained in:
Ingo Schommer 2016-10-10 10:46:19 +13:00
parent 840f275235
commit 1e478a5378
6 changed files with 20 additions and 17 deletions

View File

@ -26,7 +26,6 @@ class FormSchema {
'id' => $form->FormName(), 'id' => $form->FormName(),
'action' => $form->FormAction(), 'action' => $form->FormAction(),
'method' => $form->FormMethod(), 'method' => $form->FormMethod(),
'schema_url' => $schemaLink,
'attributes' => $form->getAttributes(), 'attributes' => $form->getAttributes(),
'data' => [], 'data' => [],
'fields' => [], 'fields' => [],

View File

@ -7,8 +7,7 @@ export default function schemaReducer(state = initialState, action = null) {
switch (action.type) { switch (action.type) {
case ACTION_TYPES.SET_SCHEMA: { case ACTION_TYPES.SET_SCHEMA: {
const id = action.payload.schema.schema_url; return deepFreeze(Object.assign({}, state, { [action.payload.id]: action.payload }));
return deepFreeze(Object.assign({}, state, { [id]: action.payload }));
} }
default: default:

View File

@ -11,14 +11,17 @@ describe('schemaReducer', () => {
describe('SET_SCHEMA', () => { describe('SET_SCHEMA', () => {
it('should create a new form', () => { it('should create a new form', () => {
const initialState = { }; const initialState = { };
const serverResponse = { id: 'TestForm', schema_url: 'URL' }; const schema = {
id: 'MySchema',
schema: { id: 'TestForm' },
};
const nextState = schemaReducer(initialState, { const nextState = schemaReducer(initialState, {
type: ACTION_TYPES.SET_SCHEMA, type: ACTION_TYPES.SET_SCHEMA,
payload: { schema: serverResponse }, payload: schema,
}); });
expect(nextState.URL.schema.id).toBe('TestForm'); expect(nextState.MySchema).toBe(schema);
}); });
}); });
}); });

View File

@ -98,13 +98,12 @@ class CampaignAdmin extends LeftAndMain implements PermissionProvider {
$adminURL = Convert::raw2js(AdminRootController::admin_url()); $adminURL = Convert::raw2js(AdminRootController::admin_url());
$json = <<<JSON $json = <<<JSON
{ {
"id": "Form_EditForm", "id": "{$adminURL}campaigns\/schema\/EditForm",
"schema": { "schema": {
"name": "EditForm", "name": "EditForm",
"id": "Form_EditForm", "id": "Form_EditForm",
"action": "schema", "action": "schema",
"method": "GET", "method": "GET",
"schema_url": "{$adminURL}campaigns\/schema\/EditForm",
"attributes": { "attributes": {
"id": "Form_EditForm", "id": "Form_EditForm",
"action": "{$adminURL}campaigns\/EditForm", "action": "{$adminURL}campaigns\/EditForm",
@ -539,8 +538,9 @@ JSON;
// Configure form to respond to validation errors with form schema // Configure form to respond to validation errors with form schema
// if requested via react. // if requested via react.
$form->setValidationResponseCallback(function() use ($form) { $form->setValidationResponseCallback(function() use ($form, $record) {
return $this->getSchemaResponse($form); $schemaId = Controller::join_links($this->Link('schema/DetailEditForm'), $record->exists() ? $record->ID : '');
return $this->getSchemaResponse($form, $schemaId);
}); });
return $form; return $form;

View File

@ -333,12 +333,13 @@ class LeftAndMain extends Controller implements PermissionProvider {
* schema if X-Formschema-Request header is set. * schema if X-Formschema-Request header is set.
* *
* @param Form $form * @param Form $form
* @param String $id Optional, will default to the current request URL
* @return HTTPResponse * @return HTTPResponse
*/ */
protected function getSchemaResponse($form) { protected function getSchemaResponse($form, $id = null) {
$request = $this->getRequest(); $request = $this->getRequest();
if($request->getHeader('X-Formschema-Request')) { if($request->getHeader('X-Formschema-Request')) {
$data = $this->getSchemaForForm($form); $data = $this->getSchemaForForm($form, $id);
$response = new HTTPResponse(Convert::raw2json($data)); $response = new HTTPResponse(Convert::raw2json($data));
$response->addHeader('Content-Type', 'application/json'); $response->addHeader('Content-Type', 'application/json');
@ -355,10 +356,12 @@ class LeftAndMain extends Controller implements PermissionProvider {
* based on the request data. * based on the request data.
* *
* @param Form $form * @param Form $form
* @param String $id Optional, will default to the current request URL
* @return array * @return array
*/ */
protected function getSchemaForForm(Form $form) { protected function getSchemaForForm(Form $form, $id = null) {
$request = $this->getRequest(); $request = $this->getRequest();
$id = $id ? $id : $request->getURL();
$return = null; $return = null;
// Valid values for the "X-Formschema-Request" header are "schema" and "state". // Valid values for the "X-Formschema-Request" header are "schema" and "state".
@ -373,7 +376,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
$schemaParts = ['schema']; $schemaParts = ['schema'];
} }
$return = ['id' => $form->FormName()]; $return = ['id' => $id];
if (in_array('schema', $schemaParts)) { if (in_array('schema', $schemaParts)) {
$schemaLink = $this->getSchemaLinkForForm($form); $schemaLink = $this->getSchemaLinkForForm($form);
@ -1302,10 +1305,11 @@ class LeftAndMain extends Controller implements PermissionProvider {
$message = _t('LeftAndMain.SAVEDUP', 'Saved.'); $message = _t('LeftAndMain.SAVEDUP', 'Saved.');
if($request->getHeader('X-Formschema-Request')) { if($request->getHeader('X-Formschema-Request')) {
$schemaId = Controller::join_links($this->Link('schema/DetailEditForm'), $id);
// Ensure that newly created records have all their data loaded back into the form. // Ensure that newly created records have all their data loaded back into the form.
$form->loadDataFrom($record); $form->loadDataFrom($record);
$form->setMessage($message, 'good'); $form->setMessage($message, 'good');
$data = $this->getSchemaForForm($form); $data = $this->getSchemaForForm($form, $schemaId);
$response = new HTTPResponse(Convert::raw2json($data)); $response = new HTTPResponse(Convert::raw2json($data));
$response->addHeader('Content-Type', 'application/json'); $response->addHeader('Content-Type', 'application/json');
} else { } else {

View File

@ -20,7 +20,6 @@ class FormSchemaTest extends SapphireTest {
'id' => 'Form_TestForm', 'id' => 'Form_TestForm',
'action' => 'Controller/TestForm', 'action' => 'Controller/TestForm',
'method' => 'POST', 'method' => 'POST',
'schema_url' => 'admin/mysection/schema',
'attributes' => [ 'attributes' => [
'id' => 'Form_TestForm', 'id' => 'Form_TestForm',
'action' => 'Controller/TestForm', 'action' => 'Controller/TestForm',
@ -171,7 +170,6 @@ class FormSchemaTest extends SapphireTest {
'id' => 'Form_TestForm', 'id' => 'Form_TestForm',
'action' => 'Controller/TestForm', 'action' => 'Controller/TestForm',
'method' => 'POST', 'method' => 'POST',
'schema_url' => 'admin/mysection/schema',
'attributes' => [ 'attributes' => [
'id' => 'Form_TestForm', 'id' => 'Form_TestForm',
'action' => 'Controller/TestForm', 'action' => 'Controller/TestForm',