mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
BUG Fix form schema to use correct ID values
API Implement creation of new changesets endpoint
This commit is contained in:
parent
2b8ef99d5e
commit
b2e8fd96ec
@ -75,6 +75,30 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
|||||||
this.handleFieldUpdate = this.handleFieldUpdate.bind(this);
|
this.handleFieldUpdate = this.handleFieldUpdate.bind(this);
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
this.removeForm = this.removeForm.bind(this);
|
this.removeForm = this.removeForm.bind(this);
|
||||||
|
this.getFormId = this.getFormId.bind(this);
|
||||||
|
this.getFormSchema = this.getFormSchema.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the schema for this form
|
||||||
|
*
|
||||||
|
* @returns {array}
|
||||||
|
*/
|
||||||
|
getFormSchema() {
|
||||||
|
return this.props.schemas[this.props.schemaUrl];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ID for this form
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getFormId() {
|
||||||
|
const schema = this.getFormSchema();
|
||||||
|
if (schema) {
|
||||||
|
return schema.id;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -184,9 +208,9 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
|||||||
*/
|
*/
|
||||||
handleFieldUpdate(event, updates, fn) {
|
handleFieldUpdate(event, updates, fn) {
|
||||||
if (typeof fn !== 'undefined') {
|
if (typeof fn !== 'undefined') {
|
||||||
fn(this.props.formId, this.props.formsActions.updateField);
|
fn(this.getFormId(), this.props.formsActions.updateField);
|
||||||
} else {
|
} else {
|
||||||
this.props.formsActions.updateField(this.props.formId, updates);
|
this.props.formsActions.updateField(this.getFormId(), updates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +247,7 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
|||||||
*/
|
*/
|
||||||
handleSubmit(event) {
|
handleSubmit(event) {
|
||||||
const schemaFields = this.props.schemas[this.props.schemaUrl].schema.fields;
|
const schemaFields = this.props.schemas[this.props.schemaUrl].schema.fields;
|
||||||
const fieldValues = this.props.forms[this.props.formId].fields
|
const fieldValues = this.props.forms[this.getFormId()].fields
|
||||||
.reduce((prev, curr) => Object.assign({}, prev, {
|
.reduce((prev, curr) => Object.assign({}, prev, {
|
||||||
[schemaFields.find(schemaField => schemaField.id === curr.id).name]: curr.value,
|
[schemaFields.find(schemaField => schemaField.id === curr.id).name]: curr.value,
|
||||||
}), {});
|
}), {});
|
||||||
@ -231,7 +255,7 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
|||||||
const submitFn = () => {
|
const submitFn = () => {
|
||||||
this.props.formsActions.submitForm(
|
this.props.formsActions.submitForm(
|
||||||
this.submitApi,
|
this.submitApi,
|
||||||
this.props.formId,
|
this.getFormId(),
|
||||||
fieldValues
|
fieldValues
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -352,8 +376,12 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const formSchema = this.props.schemas[this.props.schemaUrl];
|
const formId = this.getFormId();
|
||||||
const formState = this.props.forms[this.props.formId];
|
if (!formId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const formSchema = this.getFormSchema();
|
||||||
|
const formState = this.props.forms[formId];
|
||||||
|
|
||||||
// If the response from fetching the initial data
|
// If the response from fetching the initial data
|
||||||
// hasn't come back yet, don't render anything.
|
// hasn't come back yet, don't render anything.
|
||||||
@ -382,7 +410,7 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
|||||||
componentWillUnmount: this.removeForm,
|
componentWillUnmount: this.removeForm,
|
||||||
data: formSchema.schema.data,
|
data: formSchema.schema.data,
|
||||||
fields: fieldData,
|
fields: fieldData,
|
||||||
formId: formSchema.id,
|
formId,
|
||||||
handleSubmit: this.handleSubmit,
|
handleSubmit: this.handleSubmit,
|
||||||
mapActionsToComponents: this.mapActionsToComponents,
|
mapActionsToComponents: this.mapActionsToComponents,
|
||||||
mapFieldsToComponents: this.mapFieldsToComponents,
|
mapFieldsToComponents: this.mapFieldsToComponents,
|
||||||
@ -397,7 +425,6 @@ FormBuilderComponent.propTypes = {
|
|||||||
createFn: React.PropTypes.func,
|
createFn: React.PropTypes.func,
|
||||||
forms: React.PropTypes.object.isRequired,
|
forms: React.PropTypes.object.isRequired,
|
||||||
formsActions: React.PropTypes.object.isRequired,
|
formsActions: React.PropTypes.object.isRequired,
|
||||||
formId: React.PropTypes.string.isRequired,
|
|
||||||
handleSubmit: React.PropTypes.func,
|
handleSubmit: React.PropTypes.func,
|
||||||
schemas: React.PropTypes.object.isRequired,
|
schemas: React.PropTypes.object.isRequired,
|
||||||
schemaActions: React.PropTypes.object.isRequired,
|
schemaActions: React.PropTypes.object.isRequired,
|
||||||
|
@ -14,6 +14,13 @@ class TextField extends SilverStripeComponent {
|
|||||||
? this.props.leftTitle
|
? this.props.leftTitle
|
||||||
: this.props.title;
|
: this.props.title;
|
||||||
|
|
||||||
|
let field = null;
|
||||||
|
if (this.props.readOnly) {
|
||||||
|
field = <div><i>{this.props.value}</i></div>;
|
||||||
|
} else {
|
||||||
|
field = <input {...this.getInputProps()} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="field text">
|
<div className="field text">
|
||||||
{labelText &&
|
{labelText &&
|
||||||
@ -22,7 +29,7 @@ class TextField extends SilverStripeComponent {
|
|||||||
</label>
|
</label>
|
||||||
}
|
}
|
||||||
<div className="middleColumn">
|
<div className="middleColumn">
|
||||||
<input {...this.getInputProps()} />
|
{field}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -59,6 +66,7 @@ TextField.propTypes = {
|
|||||||
name: React.PropTypes.string.isRequired,
|
name: React.PropTypes.string.isRequired,
|
||||||
handleFieldUpdate: React.PropTypes.func,
|
handleFieldUpdate: React.PropTypes.func,
|
||||||
value: React.PropTypes.string,
|
value: React.PropTypes.string,
|
||||||
|
readOnly: React.PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TextField;
|
export default TextField;
|
||||||
|
@ -92,7 +92,6 @@ class CampaignAdmin extends SilverStripeComponent {
|
|||||||
};
|
};
|
||||||
const formBuilderProps = {
|
const formBuilderProps = {
|
||||||
createFn: this.campaignListCreateFn,
|
createFn: this.campaignListCreateFn,
|
||||||
formId: 'EditForm',
|
|
||||||
schemaUrl,
|
schemaUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -140,10 +139,7 @@ class CampaignAdmin extends SilverStripeComponent {
|
|||||||
*/
|
*/
|
||||||
renderDetailEditView() {
|
renderDetailEditView() {
|
||||||
const baseSchemaUrl = this.props.sectionConfig.forms.DetailEditForm.schemaUrl;
|
const baseSchemaUrl = this.props.sectionConfig.forms.DetailEditForm.schemaUrl;
|
||||||
const formBuilderProps = {
|
const schemaUrl = `${baseSchemaUrl}/ChangeSet/${this.props.campaignId}`;
|
||||||
formId: 'DetailEditForm',
|
|
||||||
schemaUrl: `${baseSchemaUrl}/ChangeSet/${this.props.campaignId}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="cms-middle no-preview">
|
<div className="cms-middle no-preview">
|
||||||
@ -153,7 +149,7 @@ class CampaignAdmin extends SilverStripeComponent {
|
|||||||
<h2 className="text-truncate toolbar__heading">Campaigns</h2>
|
<h2 className="text-truncate toolbar__heading">Campaigns</h2>
|
||||||
</div>
|
</div>
|
||||||
</NorthHeader>
|
</NorthHeader>
|
||||||
<FormBuilder {...formBuilderProps} />
|
<FormBuilder schemaUrl={schemaUrl} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -163,10 +159,9 @@ class CampaignAdmin extends SilverStripeComponent {
|
|||||||
* Render the view for creating a new Campaign.
|
* Render the view for creating a new Campaign.
|
||||||
*/
|
*/
|
||||||
renderCreateView() {
|
renderCreateView() {
|
||||||
const baseSchemaUrl = this.props.sectionConfig.forms.CreateEditForm.schemaUrl;
|
const baseSchemaUrl = this.props.sectionConfig.forms.DetailEditForm.schemaUrl;
|
||||||
const formBuilderProps = {
|
const formBuilderProps = {
|
||||||
createFn: this.campaignCreationView,
|
createFn: this.campaignCreationView,
|
||||||
formId: 'CreateEditForm',
|
|
||||||
schemaUrl: `${baseSchemaUrl}/ChangeSet`,
|
schemaUrl: `${baseSchemaUrl}/ChangeSet`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,12 +12,9 @@ class CampaignAdmin extends LeftAndMain implements PermissionProvider {
|
|||||||
'set',
|
'set',
|
||||||
'sets',
|
'sets',
|
||||||
'schema',
|
'schema',
|
||||||
'CreateEditForm',
|
|
||||||
'DetailEditForm',
|
'DetailEditForm',
|
||||||
'readCampaigns',
|
'readCampaigns',
|
||||||
'createCampaign',
|
|
||||||
'readCampaign',
|
'readCampaign',
|
||||||
'updateCampaign',
|
|
||||||
'deleteCampaign',
|
'deleteCampaign',
|
||||||
'publishCampaign',
|
'publishCampaign',
|
||||||
];
|
];
|
||||||
@ -63,9 +60,6 @@ class CampaignAdmin extends LeftAndMain implements PermissionProvider {
|
|||||||
'DetailEditForm' => [
|
'DetailEditForm' => [
|
||||||
'schemaUrl' => $this->Link('schema/DetailEditForm')
|
'schemaUrl' => $this->Link('schema/DetailEditForm')
|
||||||
],
|
],
|
||||||
'CreateEditForm' => [
|
|
||||||
'schemaUrl' => $this->Link('schema/CreateEditForm')
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
'campaignViewRoute' => $this->Link() . ':type?/:id?/:view?',
|
'campaignViewRoute' => $this->Link() . ':type?/:id?/:view?',
|
||||||
'itemListViewEndpoint' => $this->Link() . 'set/:id/show',
|
'itemListViewEndpoint' => $this->Link() . 'set/:id/show',
|
||||||
@ -80,10 +74,10 @@ class CampaignAdmin extends LeftAndMain implements PermissionProvider {
|
|||||||
// TODO Hardcoding schema until we can get GridField to generate a schema dynamically
|
// TODO Hardcoding schema until we can get GridField to generate a schema dynamically
|
||||||
$json = <<<JSON
|
$json = <<<JSON
|
||||||
{
|
{
|
||||||
"id": "EditForm",
|
"id": "Form_EditForm",
|
||||||
"schema": {
|
"schema": {
|
||||||
"name": "EditForm",
|
"name": "EditForm",
|
||||||
"id": "EditForm",
|
"id": "Form_EditForm",
|
||||||
"action": "schema",
|
"action": "schema",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"schema_url": "admin\/campaigns\/schema\/EditForm",
|
"schema_url": "admin\/campaigns\/schema\/EditForm",
|
||||||
@ -464,7 +458,8 @@ JSON;
|
|||||||
'DetailEditForm',
|
'DetailEditForm',
|
||||||
$fields,
|
$fields,
|
||||||
FieldList::create(
|
FieldList::create(
|
||||||
FormAction::create('save', 'Save')
|
FormAction::create('save', 'Save'),
|
||||||
|
FormAction::create('cancel', 'Cancel')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
// Configure form to respond to validation errors with form schema
|
// Configure form to respond to validation errors with form schema
|
||||||
@ -475,23 +470,6 @@ JSON;
|
|||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo Use GridFieldDetailForm once it can handle structured data and form schemas
|
|
||||||
*
|
|
||||||
* @return Form
|
|
||||||
*/
|
|
||||||
public function getCreateEditForm() {
|
|
||||||
return Form::create(
|
|
||||||
$this,
|
|
||||||
'CreateEditForm',
|
|
||||||
ChangeSet::singleton()->getCMSFields(),
|
|
||||||
FieldList::create(
|
|
||||||
FormAction::create('save', 'Save'),
|
|
||||||
FormAction::create('cancel', 'Cancel')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets user-visible url to edit a specific {@see ChangeSet}
|
* Gets user-visible url to edit a specific {@see ChangeSet}
|
||||||
*
|
*
|
||||||
@ -518,11 +496,4 @@ JSON;
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function FindReferencedChanges() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,6 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
*/
|
*/
|
||||||
protected function getSchemaForForm(Form $form) {
|
protected function getSchemaForForm(Form $form) {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$schemaParts = [];
|
|
||||||
$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".
|
||||||
@ -309,7 +308,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
$schemaParts = ['schema'];
|
$schemaParts = ['schema'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$return = ['id' => $form->getName()];
|
$return = ['id' => $form->FormName()];
|
||||||
|
|
||||||
if (in_array('schema', $schemaParts)) {
|
if (in_array('schema', $schemaParts)) {
|
||||||
$return['schema'] = $this->schema->getSchema($form);
|
$return['schema'] = $this->schema->getSchema($form);
|
||||||
@ -1166,12 +1165,18 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
|
|
||||||
// Existing or new record?
|
// Existing or new record?
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
if(substr($id,0,3) != 'new') {
|
if(is_numeric($id) && $id > 0) {
|
||||||
$record = DataObject::get_by_id($className, $id);
|
$record = DataObject::get_by_id($className, $id);
|
||||||
if($record && !$record->canEdit()) return Security::permissionFailure($this);
|
if($record && !$record->canEdit()) {
|
||||||
if(!$record || !$record->ID) $this->httpError(404, "Bad record ID #" . (int)$id);
|
return Security::permissionFailure($this);
|
||||||
|
}
|
||||||
|
if(!$record || !$record->ID) {
|
||||||
|
$this->httpError(404, "Bad record ID #" . (int)$id);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if(!singleton($this->stat('tree_class'))->canCreate()) return Security::permissionFailure($this);
|
if(!singleton($this->stat('tree_class'))->canCreate()) {
|
||||||
|
return Security::permissionFailure($this);
|
||||||
|
}
|
||||||
$record = $this->getNewItem($id, false);
|
$record = $this->getNewItem($id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1195,6 +1200,22 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new item.
|
||||||
|
*
|
||||||
|
* @param string|int $id
|
||||||
|
* @param bool $setID
|
||||||
|
* @return DataObject
|
||||||
|
*/
|
||||||
|
public function getNewItem($id, $setID = true) {
|
||||||
|
$class = $this->stat('tree_class');
|
||||||
|
$object = Injector::inst()->create($class);
|
||||||
|
if($setID) {
|
||||||
|
$object->ID = $id;
|
||||||
|
}
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
|
||||||
public function delete($data, $form) {
|
public function delete($data, $form) {
|
||||||
$className = $this->stat('tree_class');
|
$className = $this->stat('tree_class');
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@ class FormSchema {
|
|||||||
*/
|
*/
|
||||||
public function getSchema(Form $form) {
|
public function getSchema(Form $form) {
|
||||||
$request = $form->controller()->getRequest();
|
$request = $form->controller()->getRequest();
|
||||||
$params = $request->AllParams();
|
|
||||||
|
|
||||||
$schema = [
|
$schema = [
|
||||||
'name' => $form->getName(),
|
'name' => $form->getName(),
|
||||||
'id' => isset($params['ID']) ? $params['ID'] : null,
|
'id' => $form->FormName(),
|
||||||
'action' => isset($params['Action']) ? $params['Action'] : null,
|
'action' => $form->FormAction(),
|
||||||
'method' => $form->controller()->getRequest()->HttpMethod(),
|
'method' => $form->FormMethod(),
|
||||||
|
// @todo Not really reliable. Refactor into action on $this->Link('schema')
|
||||||
'schema_url' => $request->getUrl(),
|
'schema_url' => $request->getUrl(),
|
||||||
'attributes' => $form->getAttributes(),
|
'attributes' => $form->getAttributes(),
|
||||||
'data' => [],
|
'data' => [],
|
||||||
@ -57,7 +57,7 @@ class FormSchema {
|
|||||||
*/
|
*/
|
||||||
public function getState(Form $form) {
|
public function getState(Form $form) {
|
||||||
$state = [
|
$state = [
|
||||||
'id' => $form->getName(),
|
'id' => $form->FormName(),
|
||||||
'fields' => [],
|
'fields' => [],
|
||||||
'messages' => []
|
'messages' => []
|
||||||
];
|
];
|
||||||
|
@ -17,6 +17,8 @@ class ReadonlyField extends FormField {
|
|||||||
*/
|
*/
|
||||||
protected $includeHiddenField = false;
|
protected $includeHiddenField = false;
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TEXT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, a hidden field will be included in the HTML for the readonly field.
|
* If true, a hidden field will be included in the HTML for the readonly field.
|
||||||
*
|
*
|
||||||
@ -52,9 +54,30 @@ class ReadonlyField extends FormField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If $dontEscape is true the returned value will be plain text
|
||||||
|
* and should be escaped in templates via .XML
|
||||||
|
*
|
||||||
|
* If $dontEscape is false the returned value will be safely encoded,
|
||||||
|
* but should not be escaped by the frontend.
|
||||||
|
*
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
public function Value() {
|
public function Value() {
|
||||||
if($this->value) return $this->dontEscape ? $this->value : Convert::raw2xml($this->value);
|
if($this->value) {
|
||||||
else return '<i>(' . _t('FormField.NONE', 'none') . ')</i>';
|
if($this->dontEscape) {
|
||||||
|
return $this->value;
|
||||||
|
} else {
|
||||||
|
Convert::raw2xml($this->value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$value = '(' . _t('FormField.NONE', 'none') . ')';
|
||||||
|
if($this->dontEscape) {
|
||||||
|
return $value;
|
||||||
|
} else {
|
||||||
|
return '<i>'.Convert::raw2xml($value).'</i>';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAttributes() {
|
public function getAttributes() {
|
||||||
|
@ -346,10 +346,12 @@ class ChangeSet extends DataObject {
|
|||||||
|
|
||||||
public function getCMSFields() {
|
public function getCMSFields() {
|
||||||
$fields = new FieldList();
|
$fields = new FieldList();
|
||||||
$fields->merge([
|
$fields->push(TextField::create('Name'));
|
||||||
TextField::create('Name'),
|
if($this->isInDB()) {
|
||||||
ReadonlyField::create('State')
|
$state = ReadonlyField::create('State')
|
||||||
]);
|
->setDontEscape(true);
|
||||||
|
$fields->push($state); // Escape is done in react
|
||||||
|
}
|
||||||
$this->extend('updateCMSFields', $fields);
|
$this->extend('updateCMSFields', $fields);
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user