mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #6119 from open-sausages/pulls/4.0/assets-custom-actions
API Update form schema to be more responsive to dynamic form changes
This commit is contained in:
commit
89c88f0f60
@ -695,12 +695,15 @@ class Controller extends RequestHandler implements TemplateGlobalProvider {
|
||||
*
|
||||
* Caution: All parameters are expected to be URI-encoded already.
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @param string|array $arg,.. One or more link segments, or list of link segments as an array
|
||||
* @return string
|
||||
*/
|
||||
public static function join_links() {
|
||||
public static function join_links($arg = null) {
|
||||
if (func_num_args() === 1 && is_array($arg)) {
|
||||
$args = $arg;
|
||||
} else {
|
||||
$args = func_get_args();
|
||||
}
|
||||
$result = "";
|
||||
$queryargs = array();
|
||||
$fragmentIdentifier = null;
|
||||
|
@ -1424,7 +1424,7 @@ class FormField extends RequestHandler {
|
||||
* @return array
|
||||
*/
|
||||
public function getSchemaData() {
|
||||
return array_merge($this->getSchemaDataDefaults(), $this->schemaData);
|
||||
return array_replace_recursive($this->getSchemaDataDefaults(), $this->schemaData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,18 +17,16 @@ class FormSchema {
|
||||
* Gets the schema for this form as a nested array.
|
||||
*
|
||||
* @param Form $form
|
||||
* @param string $schemaLink Link to get this schema
|
||||
* @return array
|
||||
*/
|
||||
public function getSchema(Form $form) {
|
||||
$request = $form->getController()->getRequest();
|
||||
|
||||
public function getSchema(Form $form, $schemaLink) {
|
||||
$schema = [
|
||||
'name' => $form->getName(),
|
||||
'id' => $form->FormName(),
|
||||
'action' => $form->FormAction(),
|
||||
'method' => $form->FormMethod(),
|
||||
// @todo Not really reliable. Refactor into action on $this->Link('schema')
|
||||
'schema_url' => $request->getURL(),
|
||||
'schema_url' => $schemaLink,
|
||||
'attributes' => $form->getAttributes(),
|
||||
'data' => [],
|
||||
'fields' => [],
|
||||
@ -62,7 +60,10 @@ class FormSchema {
|
||||
];
|
||||
|
||||
// flattened nested fields are returned, rather than only top level fields.
|
||||
$state['fields'] = $this->getFieldStates($form->Fields());
|
||||
$state['fields'] = array_merge(
|
||||
$this->getFieldStates($form->Fields()),
|
||||
$this->getFieldStates($form->Actions())
|
||||
);
|
||||
|
||||
if($form->Message()) {
|
||||
$state['messages'][] = [
|
||||
@ -76,6 +77,7 @@ class FormSchema {
|
||||
|
||||
protected function getFieldStates($fields) {
|
||||
$states = [];
|
||||
/** @var FormField $field */
|
||||
foreach ($fields as $field) {
|
||||
$states[] = $field->getSchemaState();
|
||||
|
||||
|
@ -5,6 +5,7 @@ namespace SilverStripe\ORM\Versioning;
|
||||
use SilverStripe\Admin\CMSPreviewable;
|
||||
use SilverStripe\Assets\Thumbnail;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\ManyManyList;
|
||||
@ -109,8 +110,8 @@ class ChangeSetItem extends DataObject implements Thumbnail {
|
||||
|
||||
/**
|
||||
* Get the type of change: none, created, deleted, modified, manymany
|
||||
*
|
||||
* @return string
|
||||
* @throws UnexpectedDataException
|
||||
*/
|
||||
public function getChangeType() {
|
||||
if(!class_exists($this->ObjectClass)) {
|
||||
@ -146,7 +147,8 @@ class ChangeSetItem extends DataObject implements Thumbnail {
|
||||
* Find version of this object in the given stage
|
||||
*
|
||||
* @param string $stage
|
||||
* @return Versioned|DataObject
|
||||
* @return DataObject|Versioned
|
||||
* @throws UnexpectedDataException
|
||||
*/
|
||||
protected function getObjectInStage($stage) {
|
||||
if(!class_exists($this->ObjectClass)) {
|
||||
@ -158,8 +160,8 @@ class ChangeSetItem extends DataObject implements Thumbnail {
|
||||
|
||||
/**
|
||||
* Find latest version of this object
|
||||
*
|
||||
* @return Versioned|DataObject
|
||||
* @return DataObject|Versioned
|
||||
* @throws UnexpectedDataException
|
||||
*/
|
||||
protected function getObjectLatestVersion() {
|
||||
if(!class_exists($this->ObjectClass)) {
|
||||
@ -177,15 +179,23 @@ class ChangeSetItem extends DataObject implements Thumbnail {
|
||||
public function findReferenced() {
|
||||
if($this->getChangeType() === ChangeSetItem::CHANGE_DELETED) {
|
||||
// If deleted from stage, need to look at live record
|
||||
return $this->getObjectInStage(Versioned::LIVE)->findOwners(false);
|
||||
$record = $this->getObjectInStage(Versioned::LIVE);
|
||||
if ($record) {
|
||||
return $record->findOwners(false);
|
||||
}
|
||||
} else {
|
||||
// If changed on stage, look at owned objects there
|
||||
return $this->getObjectInStage(Versioned::DRAFT)->findOwned()->filterByCallback(function ($owned) {
|
||||
$record = $this->getObjectInStage(Versioned::DRAFT);
|
||||
if ($record) {
|
||||
return $record->findOwned()->filterByCallback(function ($owned) {
|
||||
/** @var Versioned|DataObject $owned */
|
||||
return $owned->stagesDiffer(Versioned::DRAFT, Versioned::LIVE);
|
||||
});
|
||||
}
|
||||
}
|
||||
// Empty set
|
||||
return new ArrayList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish this item, then close it.
|
||||
|
51
admin/client/dist/js/bundle.js
vendored
51
admin/client/dist/js/bundle.js
vendored
@ -331,24 +331,25 @@ return e?e.id:null}},{key:"componentDidMount",value:function r(){this.fetch()}},
|
||||
var e=this,t=arguments.length<=0||void 0===arguments[0]||arguments[0],n=arguments.length<=1||void 0===arguments[1]||arguments[1],i=[]
|
||||
return this.state.isFetching===!0?this.formSchemaPromise:(t===!0&&i.push("schema"),n===!0&&i.push("state"),this.formSchemaPromise=(0,O["default"])(this.props.schemaUrl,{headers:{"X-FormSchema-Request":i.join()
|
||||
},credentials:"same-origin"}).then(function(e){return e.json()}).then(function(t){var n=c({},{id:t.id,schema:t.schema}),i=c({},t.state)
|
||||
if("undefined"!=typeof n.id){var r={SecurityID:e.props.config.SecurityID}
|
||||
n.schema.actions.length>0&&(r[n.schema.actions[0].name]=1),e.submitApi=k["default"].createEndpointFetcher({url:n.schema.attributes.action,method:n.schema.attributes.method,defaultData:r}),e.props.schemaActions.setSchema(n)
|
||||
"undefined"!=typeof n.id&&!function(){var t={SecurityID:e.props.config.SecurityID}
|
||||
e.submitApi=function(){var i=k["default"].createEndpointFetcher({url:n.schema.attributes.action,method:n.schema.attributes.method,defaultData:t})
|
||||
return i.apply(void 0,arguments).then(function(t){if(t.schema){var n=c({},{id:t.id,schema:t.schema})
|
||||
e.props.schemaActions.setSchema(n)}return t})},e.props.schemaActions.setSchema(n)}(),"undefined"!=typeof i.id&&e.props.formActions.addForm(i)}),this.formSchemaPromise)}},{key:"handleFieldUpdate",value:function p(e,t,n){
|
||||
"function"==typeof n?n(this.getFormId(),this.props.formActions.updateField):this.props.formActions.updateField(this.getFormId(),t)}},{key:"handleAction",value:function m(e,t){this.props.formActions.setSubmitAction(this.getFormId(),t),
|
||||
"function"==typeof this.props.handleAction&&this.props.handleAction(e,t,this.getFieldValues())}},{key:"handleSubmit",value:function g(e){var t=this,n=this.getFieldValues(),i=function r(){return t.props.formActions.submitForm(t.submitApi,t.getFormId(),n)
|
||||
|
||||
}"undefined"!=typeof i.id&&e.props.formActions.addForm(i)}),this.formSchemaPromise)}},{key:"handleFieldUpdate",value:function p(e,t,n){"function"==typeof n?n(this.getFormId(),this.props.formActions.updateField):this.props.formActions.updateField(this.getFormId(),t)
|
||||
|
||||
}},{key:"handleAction",value:function m(e,t){this.props.formActions.setSubmitAction(this.getFormId(),t),"function"==typeof this.props.handleAction&&this.props.handleAction(e,t,this.getFieldValues())}},{
|
||||
key:"handleSubmit",value:function g(e){var t=this,n=this.getFieldValues(),i=function r(){return t.props.formActions.submitForm(t.submitApi,t.getFormId(),n)}
|
||||
return"undefined"!=typeof this.props.handleSubmit?this.props.handleSubmit(e,n,i):(e.preventDefault(),i())}},{key:"getFieldValues",value:function v(){var e=this,t=this.props.schemas[this.props.schemaUrl],n=t.state?t.state.fields:t.schema.fields
|
||||
}
|
||||
return"undefined"!=typeof this.props.handleSubmit?this.props.handleSubmit(e,n,i):(e.preventDefault(),i())}},{key:"getFieldValues",value:function v(){var e=this,t=this.props.schemas[this.props.schemaUrl],n=t.state?t.state.fields:t.schema.fields,i=this.getSubmitAction(),r={}
|
||||
|
||||
|
||||
return this.props.form[this.getFormId()].fields.reduce(function(t,i){var r=e.findField(n,i.id)
|
||||
return r?c({},t,o({},r.name,i.value)):t},{})}},{key:"findField",value:function y(e,t){var n=null
|
||||
return i&&(r[i]=1),this.props.form[this.getFormId()].fields.reduce(function(t,i){var r=e.findField(n,i.id)
|
||||
return r?c({},t,o({},r.name,i.value)):t},r)}},{key:"getSubmitAction",value:function y(){return this.props.form[this.getFormId()].submitAction}},{key:"findField",value:function b(e,t){var n=null
|
||||
if(!e)return n
|
||||
n=e.find(function(e){return e.id===t})
|
||||
var i=!0,r=!1,o=void 0
|
||||
try{for(var a=e[Symbol.iterator](),s;!(i=(s=a.next()).done);i=!0){var l=s.value
|
||||
if(n)break
|
||||
n=this.findField(l.children,t)}}catch(u){r=!0,o=u}finally{try{!i&&a["return"]&&a["return"]()}finally{if(r)throw o}}return n}},{key:"buildComponent",value:function b(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],n=null!==e.component?x["default"].getComponentByName(e.component):x["default"].getComponentByDataType(e.type)
|
||||
n=this.findField(l.children,t)}}catch(u){r=!0,o=u}finally{try{!i&&a["return"]&&a["return"]()}finally{if(r)throw o}}return n}},{key:"buildComponent",value:function w(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],n=null!==e.component?x["default"].getComponentByName(e.component):x["default"].getComponentByDataType(e.type)
|
||||
|
||||
|
||||
if(null===n)return null
|
||||
@ -356,27 +357,27 @@ if(null!==e.component&&void 0===n)throw Error("Component not found in injector:
|
||||
var i=c({},e,t)
|
||||
null===i.value&&delete i.value
|
||||
var r=this.props.createFn
|
||||
return"function"==typeof r?r(n,i):h["default"].createElement(n,c({key:i.id},i))}},{key:"mapFieldsToComponents",value:function w(e){var t=this
|
||||
return"function"==typeof r?r(n,i):h["default"].createElement(n,c({key:i.id},i))}},{key:"mapFieldsToComponents",value:function _(e){var t=this
|
||||
return e.map(function(e){var n={onChange:t.handleFieldUpdate}
|
||||
return e.children&&(n.children=t.mapFieldsToComponents(e.children)),t.buildComponent(e,n)})}},{key:"mapActionsToComponents",value:function _(e){var t=this,n=this.props.form[this.getFormId()]
|
||||
return e.children&&(n.children=t.mapFieldsToComponents(e.children)),t.buildComponent(e,n)})}},{key:"mapActionsToComponents",value:function C(e){var t=this,n=this.props.form[this.getFormId()]
|
||||
return e.map(function(e){var i=n&&n.submitting&&n.submitAction===e.name,r={handleClick:t.handleAction,loading:i,disabled:i||e.disabled}
|
||||
return e.children&&(r.children=t.mapActionsToComponents(e.children)),t.buildComponent(e,r)})}},{key:"mergeFieldData",value:function C(e,t){return"undefined"==typeof t?e:I["default"].recursive(!0,e,{data:t.data,
|
||||
source:t.source,messages:t.messages,valid:t.valid,value:t.value})}},{key:"removeForm",value:function T(e){this.props.formActions.removeForm(e)}},{key:"getFieldData",value:function P(e,t){var n=this
|
||||
return e.children&&(r.children=t.mapActionsToComponents(e.children)),t.buildComponent(e,r)})}},{key:"mergeFieldData",value:function T(e,t){return"undefined"==typeof t?e:I["default"].recursive(!0,e,{data:t.data,
|
||||
source:t.source,messages:t.messages,valid:t.valid,value:t.value})}},{key:"removeForm",value:function P(e){this.props.formActions.removeForm(e)}},{key:"getFieldData",value:function S(e,t){var n=this
|
||||
return e&&t&&t.fields?e.map(function(e){var i=t.fields.find(function(t){return t.id===e.id}),r=n.mergeFieldData(e,i)
|
||||
return e.children&&(r.children=n.getFieldData(e.children,t)),r}):e}},{key:"render",value:function S(){var e=this.getFormId()
|
||||
return e.children?c({},r,{children:n.getFieldData(e.children,t)}):r}):e}},{key:"render",value:function j(){var e=this.getFormId()
|
||||
if(!e)return null
|
||||
var t=this.getFormSchema(),n=this.props.form[e]
|
||||
if(!t||!t.schema)return null
|
||||
var i=c({},t.schema.attributes,{className:t.schema.attributes["class"],encType:t.schema.attributes.enctype})
|
||||
delete i["class"],delete i.enctype
|
||||
var r=this.getFieldData(t.schema.fields,n),o={actions:t.schema.actions,attributes:i,componentWillUnmount:this.removeForm,data:t.schema.data,fields:r,formId:e,handleSubmit:this.handleSubmit,mapActionsToComponents:this.mapActionsToComponents,
|
||||
mapFieldsToComponents:this.mapFieldsToComponents}
|
||||
return h["default"].createElement(E["default"],o)}}]),t}(C["default"])
|
||||
var r=this.getFieldData(t.schema.fields,n),o=this.getFieldData(t.schema.actions,n),a={actions:o,attributes:i,componentWillUnmount:this.removeForm,data:t.schema.data,fields:r,formId:e,handleSubmit:this.handleSubmit,
|
||||
mapActionsToComponents:this.mapActionsToComponents,mapFieldsToComponents:this.mapFieldsToComponents}
|
||||
return h["default"].createElement(E["default"],a)}}]),t}(C["default"])
|
||||
D.propTypes={config:h["default"].PropTypes.object,createFn:h["default"].PropTypes.func,form:h["default"].PropTypes.object.isRequired,formActions:h["default"].PropTypes.object.isRequired,handleSubmit:h["default"].PropTypes.func,
|
||||
handleAction:h["default"].PropTypes.func,schemas:h["default"].PropTypes.object.isRequired,schemaActions:h["default"].PropTypes.object.isRequired,schemaUrl:h["default"].PropTypes.string.isRequired},t["default"]=(0,
|
||||
m.connect)(u,d)(D)},function(e,t){e.exports=ReactRedux},,function(e,t,n){"use strict"
|
||||
function i(e){return function(t){t({type:u.ACTION_TYPES.REMOVE_FORM,payload:{formId:e}})}}function r(e,t){return function(n){n({type:u.ACTION_TYPES.UPDATE_FIELD,payload:{formId:e,updates:t}})}}function o(e){
|
||||
return function(t){t({type:u.ACTION_TYPES.ADD_FORM,payload:{formState:e}})}}function a(e,t,n){return function(i){var r={"X-Formschema-Request":"state","X-Requested-With":"XMLHttpRequest"}
|
||||
return function(t){t({type:u.ACTION_TYPES.ADD_FORM,payload:{formState:e}})}}function a(e,t,n){return function(i){var r={"X-Formschema-Request":"schema,state","X-Requested-With":"XMLHttpRequest"}
|
||||
return i({type:u.ACTION_TYPES.SUBMIT_FORM_REQUEST,payload:{formId:t}}),e(l({ID:t},n),r).then(function(e){return i({type:u.ACTION_TYPES.SUBMIT_FORM_SUCCESS,payload:{response:e}}),e})["catch"](function(e){
|
||||
throw e.response.text().then(function(e){return i({type:u.ACTION_TYPES.SUBMIT_FORM_FAILURE,payload:{formId:t,error:e}}),e})})}}function s(e,t){return function(n){n({type:u.ACTION_TYPES.SET_SUBMIT_ACTION,
|
||||
payload:{formId:e,submitAction:t}})}}Object.defineProperty(t,"__esModule",{value:!0})
|
||||
@ -2408,15 +2409,17 @@ multiline:!0,crumbs:this.props.breadcrumbs})),p["default"].createElement("div",{
|
||||
|
||||
}},{key:"renderItemListView",value:function h(){var e={sectionConfig:this.props.sectionConfig,campaignId:this.props.params.id,itemListViewEndpoint:this.props.sectionConfig.itemListViewEndpoint,publishApi:this.publishApi,
|
||||
handleBackButtonClick:this.handleBackButtonClick.bind(this)}
|
||||
return p["default"].createElement(A["default"],e)}},{key:"renderDetailEditView",value:function m(){var e=this.props.sectionConfig.form.DetailEditForm.schemaUrl,t={createFn:this.campaignEditCreateFn.bind(this),
|
||||
schemaUrl:e+"/"+this.props.params.id}
|
||||
return p["default"].createElement(A["default"],e)}},{key:"renderDetailEditView",value:function m(){var e=this.props.sectionConfig.form.DetailEditForm.schemaUrl,t=e
|
||||
this.props.params.id>0&&(t=e+"/"+this.props.params.id)
|
||||
var n={createFn:this.campaignEditCreateFn.bind(this),schemaUrl:t}
|
||||
return p["default"].createElement("div",{className:"cms-content__inner"},p["default"].createElement(x["default"],{showBackButton:!0,handleBackButtonClick:this.handleBackButtonClick},p["default"].createElement(C["default"],{
|
||||
multiline:!0,crumbs:this.props.breadcrumbs})),p["default"].createElement("div",{className:"panel panel--padded panel--scrollable panel--single-toolbar"},p["default"].createElement("div",{className:"form--inline"
|
||||
},p["default"].createElement(I["default"],t))))}},{key:"renderCreateView",value:function g(){var e=this.props.sectionConfig.form.DetailEditForm.schemaUrl,t={createFn:this.campaignAddCreateFn.bind(this),
|
||||
schemaUrl:e+"/"+this.props.params.id}
|
||||
},p["default"].createElement(I["default"],n))))}},{key:"renderCreateView",value:function g(){var e=this.props.sectionConfig.form.DetailEditForm.schemaUrl,t=e
|
||||
this.props.params.id>0&&(t=e+"/"+this.props.params.id)
|
||||
var n={createFn:this.campaignAddCreateFn.bind(this),schemaUrl:t}
|
||||
return p["default"].createElement("div",{className:"cms-content__inner"},p["default"].createElement(x["default"],{showBackButton:!0,handleBackButtonClick:this.handleBackButtonClick},p["default"].createElement(C["default"],{
|
||||
multiline:!0,crumbs:this.props.breadcrumbs})),p["default"].createElement("div",{className:"panel panel--padded panel--scrollable panel--single-toolbar"},p["default"].createElement("div",{className:"form--inline"
|
||||
},p["default"].createElement(I["default"],t))))}},{key:"campaignEditCreateFn",value:function v(e,t){var n=this,i=this.props.sectionConfig.url
|
||||
},p["default"].createElement(I["default"],n))))}},{key:"campaignEditCreateFn",value:function v(e,t){var n=this,i=this.props.sectionConfig.url
|
||||
if("action_cancel"===t.name){var r=d({},t,{handleClick:function o(e){e.preventDefault(),n.props.router.push(i)}})
|
||||
return p["default"].createElement(e,d({key:t.id},r))}return p["default"].createElement(e,d({key:t.id},t))}},{key:"campaignAddCreateFn",value:function b(e,t){var n=this,i=this.props.sectionConfig.url
|
||||
if("action_cancel"===t.name){var r=d({},t,{handleClick:function o(e){e.preventDefault(),n.props.router.push(i)}})
|
||||
|
@ -105,16 +105,24 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
||||
SecurityID: this.props.config.SecurityID,
|
||||
};
|
||||
|
||||
if (formSchema.schema.actions.length > 0) {
|
||||
defaultData[formSchema.schema.actions[0].name] = 1;
|
||||
}
|
||||
|
||||
this.submitApi = backend.createEndpointFetcher({
|
||||
this.submitApi = (...args) => {
|
||||
const endPoint = backend.createEndpointFetcher({
|
||||
url: formSchema.schema.attributes.action,
|
||||
method: formSchema.schema.attributes.method,
|
||||
defaultData,
|
||||
});
|
||||
|
||||
// Ensure that schema changes are handled prior to updating state
|
||||
return endPoint(...args)
|
||||
.then((response) => {
|
||||
if (response.schema) {
|
||||
const newSchema = Object.assign({}, { id: response.id, schema: response.schema });
|
||||
this.props.schemaActions.setSchema(newSchema);
|
||||
}
|
||||
return response;
|
||||
});
|
||||
};
|
||||
|
||||
this.props.schemaActions.setSchema(formSchema);
|
||||
}
|
||||
|
||||
@ -248,6 +256,14 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
||||
? schema.state.fields
|
||||
: schema.schema.fields;
|
||||
|
||||
// Set action
|
||||
const action = this.getSubmitAction();
|
||||
const values = {};
|
||||
if (action) {
|
||||
values[action] = 1;
|
||||
}
|
||||
|
||||
// Reduce all other fields
|
||||
return this.props.form[this.getFormId()].fields
|
||||
.reduce((prev, curr) => {
|
||||
const match = this.findField(fields, curr.id);
|
||||
@ -258,7 +274,11 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
||||
return Object.assign({}, prev, {
|
||||
[match.name]: curr.value,
|
||||
});
|
||||
}, {});
|
||||
}, values);
|
||||
}
|
||||
|
||||
getSubmitAction() {
|
||||
return this.props.form[this.getFormId()].submitAction;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -419,7 +439,9 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
||||
const data = this.mergeFieldData(field, state);
|
||||
|
||||
if (field.children) {
|
||||
data.children = this.getFieldData(field.children, formState);
|
||||
return Object.assign({}, data, {
|
||||
children: this.getFieldData(field.children, formState),
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
@ -451,9 +473,10 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
||||
delete attributes.enctype;
|
||||
|
||||
const fieldData = this.getFieldData(formSchema.schema.fields, formState);
|
||||
const actionData = this.getFieldData(formSchema.schema.actions, formState);
|
||||
|
||||
const formProps = {
|
||||
actions: formSchema.schema.actions,
|
||||
actions: actionData,
|
||||
attributes,
|
||||
componentWillUnmount: this.removeForm,
|
||||
data: formSchema.schema.data,
|
||||
|
@ -63,6 +63,7 @@ describe('FormBuilderComponent', () => {
|
||||
props = {
|
||||
form: {
|
||||
MyForm: {
|
||||
submitAction: 'action_save',
|
||||
fields: [
|
||||
{ id: 'fieldOne', value: 'valOne' },
|
||||
{ id: 'fieldTwo', value: null },
|
||||
@ -89,6 +90,7 @@ describe('FormBuilderComponent', () => {
|
||||
|
||||
fieldValues = formBuilder.getFieldValues();
|
||||
expect(fieldValues).toEqual({
|
||||
action_save: 1,
|
||||
fieldOne: 'valOne',
|
||||
fieldTwo: null,
|
||||
});
|
||||
|
@ -170,9 +170,13 @@ class CampaignAdmin extends SilverStripeComponent {
|
||||
*/
|
||||
renderDetailEditView() {
|
||||
const baseSchemaUrl = this.props.sectionConfig.form.DetailEditForm.schemaUrl;
|
||||
let schemaUrl = baseSchemaUrl;
|
||||
if (this.props.params.id > 0) {
|
||||
schemaUrl = `${baseSchemaUrl}/${this.props.params.id}`;
|
||||
}
|
||||
const formBuilderProps = {
|
||||
createFn: this.campaignEditCreateFn.bind(this),
|
||||
schemaUrl: `${baseSchemaUrl}/${this.props.params.id}`,
|
||||
schemaUrl,
|
||||
};
|
||||
|
||||
return (
|
||||
@ -195,9 +199,13 @@ class CampaignAdmin extends SilverStripeComponent {
|
||||
*/
|
||||
renderCreateView() {
|
||||
const baseSchemaUrl = this.props.sectionConfig.form.DetailEditForm.schemaUrl;
|
||||
let schemaUrl = baseSchemaUrl;
|
||||
if (this.props.params.id > 0) {
|
||||
schemaUrl = `${baseSchemaUrl}/${this.props.params.id}`;
|
||||
}
|
||||
const formBuilderProps = {
|
||||
createFn: this.campaignAddCreateFn.bind(this),
|
||||
schemaUrl: `${baseSchemaUrl}/${this.props.params.id}`,
|
||||
schemaUrl,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -58,7 +58,7 @@ export function addForm(formState) {
|
||||
export function submitForm(submitApi, formId, fieldValues) {
|
||||
return (dispatch) => {
|
||||
const headers = {
|
||||
'X-Formschema-Request': 'state',
|
||||
'X-Formschema-Request': 'schema,state',
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
};
|
||||
dispatch({
|
||||
|
@ -372,7 +372,8 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
$return = ['id' => $form->FormName()];
|
||||
|
||||
if (in_array('schema', $schemaParts)) {
|
||||
$return['schema'] = $this->schema->getSchema($form);
|
||||
$schemaLink = $this->getSchemaLinkForForm($form);
|
||||
$return['schema'] = $this->schema->getSchema($form, $schemaLink);
|
||||
}
|
||||
|
||||
if (in_array('state', $schemaParts)) {
|
||||
@ -382,6 +383,22 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get link to schema url for a given form
|
||||
*
|
||||
* @param Form $form
|
||||
* @return string
|
||||
*/
|
||||
protected function getSchemaLinkForForm(Form $form) {
|
||||
$parts = [$this->Link('schema'), $form->getName()];
|
||||
if (($record = $form->getRecord()) && $record->isInDB()) {
|
||||
$parts[] = $record->ID;
|
||||
} elseif (($data = $form->getData()) && !empty($data['ID'])) {
|
||||
$parts[] = $data['ID'];
|
||||
}
|
||||
return Controller::join_links($parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
* @return boolean
|
||||
|
@ -792,6 +792,7 @@ specific functions.
|
||||
Run `composer require --dev 'phpunit/phpunit:~4.8'` on existing projects to pull in the new dependency.
|
||||
* Admin URL can now be configured via custom Director routing rule
|
||||
* `Controller::init` visibility changed to protected. Use `Controller::doInit()` instead.
|
||||
* `Controller::join_links` supports an array of link sections.
|
||||
* `Object::useCustomClass` has been removed. You should use the config API with Injector instead.
|
||||
* `Object::invokeWithExtensions` now has the same method signature as `Object::extend` and behaves the same way.
|
||||
* `ServiceConfigurationLocator` is now an interface not a class.
|
||||
|
@ -283,6 +283,11 @@ class ControllerTest extends FunctionalTest {
|
||||
|
||||
/* Does type-safe checks for zero value */
|
||||
$this->assertEquals("my-page/0", Controller::join_links("my-page", 0));
|
||||
|
||||
// Test array args
|
||||
$this->assertEquals("admin/crm/MyForm?a=1&b=2&c=3",
|
||||
Controller::join_links(["?a=1", "admin/crm", "?b=2", "MyForm?c=3"])
|
||||
);
|
||||
}
|
||||
|
||||
public function testLink() {
|
||||
|
@ -10,9 +10,6 @@ use SilverStripe\Forms\RequiredFields;
|
||||
use SilverStripe\Forms\FormAction;
|
||||
use SilverStripe\Forms\PopoverField;
|
||||
|
||||
|
||||
|
||||
|
||||
class FormSchemaTest extends SapphireTest {
|
||||
|
||||
public function testGetSchema() {
|
||||
@ -23,7 +20,7 @@ class FormSchemaTest extends SapphireTest {
|
||||
'id' => 'Form_TestForm',
|
||||
'action' => 'Controller/TestForm',
|
||||
'method' => 'POST',
|
||||
'schema_url' => '',
|
||||
'schema_url' => 'admin/mysection/schema',
|
||||
'attributes' => [
|
||||
'id' => 'Form_TestForm',
|
||||
'action' => 'Controller/TestForm',
|
||||
@ -56,7 +53,7 @@ class FormSchemaTest extends SapphireTest {
|
||||
'actions' => []
|
||||
];
|
||||
|
||||
$schema = $formSchema->getSchema($form);
|
||||
$schema = $formSchema->getSchema($form, 'admin/mysection/schema');
|
||||
$this->assertInternalType('array', $schema);
|
||||
$this->assertJsonStringEqualsJsonString(json_encode($expected), json_encode($schema));
|
||||
}
|
||||
@ -174,7 +171,7 @@ class FormSchemaTest extends SapphireTest {
|
||||
'id' => 'Form_TestForm',
|
||||
'action' => 'Controller/TestForm',
|
||||
'method' => 'POST',
|
||||
'schema_url' => '',
|
||||
'schema_url' => 'admin/mysection/schema',
|
||||
'attributes' => [
|
||||
'id' => 'Form_TestForm',
|
||||
'action' => 'Controller/TestForm',
|
||||
@ -339,9 +336,27 @@ class FormSchemaTest extends SapphireTest {
|
||||
]
|
||||
];
|
||||
|
||||
$schema = $formSchema->getSchema($form);
|
||||
$schema = $formSchema->getSchema($form, 'admin/mysection/schema');
|
||||
|
||||
$this->assertInternalType('array', $schema);
|
||||
$this->assertJsonStringEqualsJsonString(json_encode($expected), json_encode($schema));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that schema is merged correctly
|
||||
*/
|
||||
public function testMergeSchema() {
|
||||
$publishAction = FormAction::create('publish', 'Publish');
|
||||
$publishAction->setIcon('save');
|
||||
$publishAction->setSchemaData(['data' => ['buttonStyle' => 'primary']]);
|
||||
$schema = $publishAction->getSchemaData();
|
||||
$this->assertEquals(
|
||||
[
|
||||
'icon' => 'save',
|
||||
'buttonStyle' => 'primary',
|
||||
],
|
||||
$schema['data']
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user