mirror of
https://github.com/silverstripe/silverstripe-userforms.git
synced 2024-10-22 17:05:42 +02:00
API Add field group (unfinished)
This commit is contained in:
parent
b1c86f346f
commit
a8ee26ec50
@ -37,12 +37,17 @@ class UserFormFieldEditorExtension extends DataExtension {
|
|||||||
$this->createInitialFormStep(true);
|
$this->createInitialFormStep(true);
|
||||||
|
|
||||||
$editableColumns = new GridFieldEditableColumns();
|
$editableColumns = new GridFieldEditableColumns();
|
||||||
|
$fieldClasses = $this->getEditableFieldClasses();
|
||||||
$editableColumns->setDisplayFields(array(
|
$editableColumns->setDisplayFields(array(
|
||||||
'ClassName' => function($record, $column, $grid) {
|
'ClassName' => function($record, $column, $grid) use ($fieldClasses) {
|
||||||
if($record instanceof EditableFormStep) {
|
if($record instanceof EditableFormStep) {
|
||||||
return new LabelField($column, "Page Break");
|
return new LabelField($column, _t('UserFormFieldEditorExtension.PAGE_BREAK', 'Page Break'));
|
||||||
|
} elseif($record instanceof EditableFieldGroup) {
|
||||||
|
return new LabelField($column, _t('UserFormFieldEditorExtension.FIELD_GROUP_START', 'Field Group (start)'));
|
||||||
|
} else if($record instanceof EditableFieldGroupEnd) {
|
||||||
|
return new LabelField($column, _t('UserFormFieldEditorExtension.FIELD_GROUP_END', 'Field Group (end)'));
|
||||||
} else {
|
} else {
|
||||||
return DropdownField::create($column, '', $this->getEditableFieldClasses());
|
return DropdownField::create($column, '', $fieldClasses);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'Title' => function($record, $column, $grid) {
|
'Title' => function($record, $column, $grid) {
|
||||||
@ -55,8 +60,15 @@ class UserFormFieldEditorExtension extends DataExtension {
|
|||||||
->addComponents(
|
->addComponents(
|
||||||
$editableColumns,
|
$editableColumns,
|
||||||
new GridFieldButtonRow(),
|
new GridFieldButtonRow(),
|
||||||
$addField = new GridFieldAddNewInlineButton(),
|
GridFieldAddItemInlineButton::create('EditableFormField')
|
||||||
$addStep = new GridFieldAddItemInlineButton('EditableFormStep'),
|
->setTitle(_t('UserFormFieldEditorExtension.ADD_FIELD', 'Add Field'))
|
||||||
|
->setButtonClass('ss-ui-action-constructive'),
|
||||||
|
GridFieldAddItemInlineButton::create('EditableFormStep')
|
||||||
|
->setTitle(_t('UserFormFieldEditorExtension.ADD_PAGE_BREAK', 'Add Page Break'))
|
||||||
|
->setExtraClass('uf-gridfield-steprow'),
|
||||||
|
GridFieldAddItemInlineButton::create(array('EditableFieldGroup', 'EditableFieldGroupEnd'))
|
||||||
|
->setTitle(_t('UserFormFieldEditorExtension.ADD_FIELD_GROUP', 'Add Field Group'))
|
||||||
|
->setExtraClass('uf-gridfield-grouprow'),
|
||||||
new GridFieldEditButton(),
|
new GridFieldEditButton(),
|
||||||
new GridFieldDeleteAction(),
|
new GridFieldDeleteAction(),
|
||||||
new GridFieldToolbarHeader(),
|
new GridFieldToolbarHeader(),
|
||||||
@ -64,9 +76,6 @@ class UserFormFieldEditorExtension extends DataExtension {
|
|||||||
new GridState_Component(),
|
new GridState_Component(),
|
||||||
new GridFieldDetailForm()
|
new GridFieldDetailForm()
|
||||||
);
|
);
|
||||||
$addField->setTitle('Add Field');
|
|
||||||
$addStep->setTitle('Add Page Break');
|
|
||||||
$addStep->setExtraClass('uf-gridfield-steprow');
|
|
||||||
|
|
||||||
$fieldEditor = GridField::create(
|
$fieldEditor = GridField::create(
|
||||||
'Fields',
|
'Fields',
|
||||||
@ -126,21 +135,20 @@ class UserFormFieldEditorExtension extends DataExtension {
|
|||||||
$classes = ClassInfo::getValidSubClasses('EditableFormField');
|
$classes = ClassInfo::getValidSubClasses('EditableFormField');
|
||||||
|
|
||||||
// Remove classes we don't want to display in the dropdown.
|
// Remove classes we don't want to display in the dropdown.
|
||||||
$classes = array_diff($classes, array(
|
|
||||||
'EditableFormField',
|
|
||||||
'EditableMultipleOptionField'
|
|
||||||
));
|
|
||||||
|
|
||||||
$editableFieldClasses = array();
|
$editableFieldClasses = array();
|
||||||
|
foreach ($classes as $class) {
|
||||||
foreach ($classes as $key => $className) {
|
if(in_array($class, array('EditableFormField', 'EditableMultipleOptionField'))
|
||||||
$singleton = singleton($className);
|
|| Config::inst()->get($class, 'hidden')
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$singleton = singleton($class);
|
||||||
if(!$singleton->canCreate()) {
|
if(!$singleton->canCreate()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$editableFieldClasses[$className] = $singleton->i18n_singular_name();
|
$editableFieldClasses[$class] = $singleton->i18n_singular_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $editableFieldClasses;
|
return $editableFieldClasses;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Provides an alternative to GridFieldAddNewInlineButton, but allows you to set a classname
|
* Provides an alternative to GridFieldAddNewInlineButton, but allows you to set a classname
|
||||||
*/
|
*/
|
||||||
class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_SaveHandler {
|
class GridFieldAddItemInlineButton extends Object implements GridField_HTMLProvider, GridField_SaveHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment id
|
* Fragment id
|
||||||
@ -14,6 +14,13 @@ class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_
|
|||||||
*/
|
*/
|
||||||
protected $fragment;
|
protected $fragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additonal CSS classes for the button
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $buttonClass = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button title
|
* Button title
|
||||||
*
|
*
|
||||||
@ -22,11 +29,11 @@ class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_
|
|||||||
protected $title;
|
protected $title;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class name
|
* Class names
|
||||||
*
|
*
|
||||||
* @var string
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $modelClass = null;
|
protected $modelClasses = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extra CSS classes for this row
|
* Extra CSS classes for this row
|
||||||
@ -35,14 +42,13 @@ class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_
|
|||||||
*/
|
*/
|
||||||
protected $extraClass = null;
|
protected $extraClass = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $class Name of class to default to
|
* @param array $classes Class or list of classes to create.
|
||||||
|
* If you enter more than one class, each click of the "add" button will create one of each
|
||||||
* @param string $fragment The fragment to render the button into
|
* @param string $fragment The fragment to render the button into
|
||||||
*/
|
*/
|
||||||
public function __construct($class, $fragment = 'buttons-before-left') {
|
public function __construct($classes, $fragment = 'buttons-before-left') {
|
||||||
$this->setClass($class);
|
$this->setClasses($classes);
|
||||||
$this->setFragment($fragment);
|
$this->setFragment($fragment);
|
||||||
$this->setTitle(_t('GridFieldExtensions.ADD', 'Add'));
|
$this->setTitle(_t('GridFieldExtensions.ADD', 'Add'));
|
||||||
}
|
}
|
||||||
@ -88,43 +94,54 @@ class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getHTMLFragments($grid) {
|
public function getHTMLFragments($grid) {
|
||||||
if($grid->getList() && !singleton($grid->getModelClass())->canCreate()) {
|
foreach($this->getClasses() as $class) {
|
||||||
return array();
|
if(!singleton($class)->canCreate()) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$fragment = $this->getFragment();
|
|
||||||
|
|
||||||
if(!$editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns')) {
|
if(!$editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns')) {
|
||||||
throw new Exception('Inline adding requires the editable columns component');
|
throw new Exception('Inline adding requires the editable columns component');
|
||||||
}
|
}
|
||||||
|
|
||||||
Requirements::javascript(THIRDPARTY_DIR . '/javascript-templates/tmpl.js');
|
Requirements::javascript(THIRDPARTY_DIR . '/javascript-templates/tmpl.js');
|
||||||
GridFieldExtensions::include_requirements();
|
GridFieldExtensions::include_requirements();
|
||||||
Requirements::javascript(USERFORMS_DIR . '/javascript/GridFieldAddItemInlineButton.js');
|
Requirements::javascript(USERFORMS_DIR . '/javascript/GridFieldExtensions.js');
|
||||||
|
|
||||||
|
// Build button content
|
||||||
$data = new ArrayData(array(
|
$data = new ArrayData(array(
|
||||||
'Title' => $this->getTitle(),
|
'Title' => $this->getTitle(),
|
||||||
'TemplateName' => $this->getRowTemplateName()
|
'ButtonClass' => $this->getButtonClass(),
|
||||||
|
'TemplateNames' => json_encode($this->getRowTemplateNames())
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Build template body
|
||||||
|
$templates = '';
|
||||||
|
foreach($this->getClasses() as $class) {
|
||||||
|
$templates .= $this->getItemRowTemplateFor($grid, $editable, $class);
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
$fragment => $data->renderWith(__CLASS__),
|
$this->getFragment() => $data->renderWith(__CLASS__),
|
||||||
'after' => $this->getItemRowTemplate($grid, $editable)
|
'after' => $templates
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Because getRowTemplate is private
|
* Get the template for a given class
|
||||||
*
|
*
|
||||||
* @param GridField $grid
|
* @param GridField $grid
|
||||||
* @param GridFieldEditableColumns $editable
|
* @param GridFieldEditableColumns $editable
|
||||||
|
* @param string $class Name of class
|
||||||
* @return type
|
* @return type
|
||||||
*/
|
*/
|
||||||
protected function getItemRowTemplate(GridField $grid, GridFieldEditableColumns $editable) {
|
protected function getItemRowTemplateFor(GridField $grid, GridFieldEditableColumns $editable, $class) {
|
||||||
$columns = new ArrayList();
|
$columns = new ArrayList();
|
||||||
$handled = array_keys($editable->getDisplayFields($grid));
|
$handled = array_keys($editable->getDisplayFields($grid));
|
||||||
|
|
||||||
$record = Object::create($this->getClass());
|
$record = Object::create($class);
|
||||||
|
|
||||||
$fields = $editable->getFields($grid, $record);
|
$fields = $editable->getFields($grid, $record);
|
||||||
|
|
||||||
@ -134,7 +151,7 @@ class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_
|
|||||||
$field = $fields->dataFieldByName($column);
|
$field = $fields->dataFieldByName($column);
|
||||||
if($field) {
|
if($field) {
|
||||||
$field->setName(sprintf(
|
$field->setName(sprintf(
|
||||||
'%s[%s][%s][{%%=o.num%%}][%s]', $grid->getName(), __CLASS__, $this->getClass(), $field->getName()
|
'%s[%s][{%%=o.num%%}][%s][%s]', $grid->getName(), __CLASS__, $class, $field->getName()
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
$field = $fields->fieldByName($column);
|
$field = $fields->fieldByName($column);
|
||||||
@ -160,30 +177,50 @@ class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_
|
|||||||
$data = new ArrayData(array(
|
$data = new ArrayData(array(
|
||||||
'Columns' => $columns,
|
'Columns' => $columns,
|
||||||
'ExtraClass' => $this->getExtraClass(),
|
'ExtraClass' => $this->getExtraClass(),
|
||||||
'RecordClass' => $this->getClass(),
|
'RecordClass' => $class,
|
||||||
'TemplateName' => $this->getRowTemplateName()
|
'TemplateName' => $this->getRowTemplateNameFor($class)
|
||||||
));
|
));
|
||||||
return $data->renderWith(__CLASS__ . '_Row');
|
return $data->renderWith('GridFieldAddItemTemplate');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleSave(GridField $grid, DataObjectInterface $record) {
|
public function handleSave(GridField $grid, DataObjectInterface $record) {
|
||||||
$list = $grid->getList();
|
// Check that this submission relates to this component
|
||||||
$value = $grid->Value();
|
$value = $grid->Value();
|
||||||
$class = $this->getClass();
|
if(empty($value[__CLASS__]) || !is_array($value[__CLASS__])) {
|
||||||
|
|
||||||
if(!isset($value[__CLASS__][$class]) || !is_array($value[__CLASS__][$class])) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The way that this component works is that only the first component added to a form will
|
||||||
|
// be responsible for saving all records for each submission, in order to ensure creation
|
||||||
|
// and sort order is maintained
|
||||||
|
$addInlineComponents = $grid->getConfig()->getComponentsByType(__CLASS__);
|
||||||
|
if($this !== $addInlineComponents->first()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get allowed classes
|
||||||
|
$classes = array();
|
||||||
|
foreach($addInlineComponents as $component) {
|
||||||
|
$classes = array_merge($classes, $component->getClasses());
|
||||||
|
}
|
||||||
|
$classes = array_filter($classes, function($class) {
|
||||||
|
return singleton($class)->canCreate();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get form
|
||||||
$editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns');
|
$editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns');
|
||||||
$form = $editable->getForm($grid, $record);
|
$form = $editable->getForm($grid, $record);
|
||||||
|
|
||||||
if(!singleton($class)->canCreate()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process records matching the specified class
|
// Process records matching the specified class
|
||||||
foreach($value[__CLASS__][$class] as $fields) {
|
$list = $grid->getList();
|
||||||
|
foreach($value[__CLASS__] as $row) {
|
||||||
|
$fields = reset($row);
|
||||||
|
$class = key($row);
|
||||||
|
if(!in_array($class, $classes)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$item = $class::create();
|
$item = $class::create();
|
||||||
$extra = array();
|
$extra = array();
|
||||||
|
|
||||||
@ -200,21 +237,24 @@ class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the class of the object to create
|
* Get the classes of the objects to create
|
||||||
*
|
*
|
||||||
* @return string
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getClass() {
|
public function getClasses() {
|
||||||
return $this->modelClass;
|
return $this->modelClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the class to create
|
* Specify the classes to create
|
||||||
*
|
*
|
||||||
* @param string $class
|
* @param array $classes
|
||||||
*/
|
*/
|
||||||
public function setClass($class) {
|
public function setClasses($classes) {
|
||||||
$this->modelClass = $class;
|
if(!is_array($classes)) {
|
||||||
|
$classes = array($classes);
|
||||||
|
}
|
||||||
|
$this->modelClasses = $classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -230,17 +270,52 @@ class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_
|
|||||||
* Sets extra CSS classes for this row
|
* Sets extra CSS classes for this row
|
||||||
*
|
*
|
||||||
* @param string $extraClass
|
* @param string $extraClass
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setExtraClass($extraClass) {
|
public function setExtraClass($extraClass) {
|
||||||
$this->extraClass = $extraClass;
|
$this->extraClass = $extraClass;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get name of item template
|
* Get extra button class
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getRowTemplateName() {
|
public function getButtonClass() {
|
||||||
return 'ss-gridfield-add-inline-template-' . $this->getClass();
|
return $this->buttonClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets extra CSS classes for this button
|
||||||
|
*
|
||||||
|
* @param string $buttonClass
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setButtonClass($buttonClass) {
|
||||||
|
$this->buttonClass = $buttonClass;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get names of all item templates
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRowTemplateNames() {
|
||||||
|
$self = $this;
|
||||||
|
return array_map(function($class) use ($self) {
|
||||||
|
return $this->getRowTemplateNameFor($class);
|
||||||
|
}, $this->getClasses());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the template name for a single class
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getRowTemplateNameFor($class) {
|
||||||
|
return "ss-gridfield-add-inline-template-{$class}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
code/model/editableformfields/EditableFieldGroup.php
Normal file
16
code/model/editableformfields/EditableFieldGroup.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that this ends a group of fields
|
||||||
|
*/
|
||||||
|
class EditableFieldGroup extends EditableFormField {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable selection of group class
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $hidden = true;
|
||||||
|
|
||||||
|
}
|
16
code/model/editableformfields/EditableFieldGroupEnd.php
Normal file
16
code/model/editableformfields/EditableFieldGroupEnd.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that this ends a group of fields
|
||||||
|
*/
|
||||||
|
class EditableFieldGroupEnd extends EditableFormField {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable selection of group class
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $hidden = true;
|
||||||
|
|
||||||
|
}
|
@ -8,6 +8,14 @@
|
|||||||
*/
|
*/
|
||||||
class EditableFormField extends DataObject {
|
class EditableFormField extends DataObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to true to hide from class selector
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $hidden = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default sort order
|
* Default sort order
|
||||||
*
|
*
|
||||||
|
@ -6,6 +6,14 @@
|
|||||||
*/
|
*/
|
||||||
class EditableFormStep extends EditableFormField {
|
class EditableFormStep extends EditableFormField {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable selection of step class
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $hidden = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
* @var string
|
* @var string
|
||||||
|
@ -18,21 +18,12 @@
|
|||||||
|
|
||||||
$(".ss-gridfield-add-new-item-inline").entwine({
|
$(".ss-gridfield-add-new-item-inline").entwine({
|
||||||
onclick: function() {
|
onclick: function() {
|
||||||
// Get custom class from button
|
// Create each template
|
||||||
var template = this.data('template');
|
var gridfield = this.getGridField();
|
||||||
this.getGridField().trigger("addnewiteminline", template);
|
$.each(this.data('template-names'), function(index, template) {
|
||||||
return false;
|
console.log(template);
|
||||||
}
|
gridfield.trigger("addnewiteminline", template);
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".ss-gridfield-delete-inline").entwine({
|
|
||||||
onclick: function() {
|
|
||||||
var msg = ss.i18n._t("GridFieldExtensions.CONFIRMDEL", "Are you sure you want to delete this?");
|
|
||||||
|
|
||||||
if(confirm(msg)) {
|
|
||||||
this.parents("tr").remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -1,3 +1,3 @@
|
|||||||
<button href="$Link" class="ss-gridfield-add-new-item-inline ss-ui-button" data-icon="add" data-template="$TemplateName.ATT">
|
<button href="$Link" class="ss-gridfield-add-new-item-inline ss-ui-button $ButtonClass" data-icon="add" data-template-names="$TemplateNames.ATT">
|
||||||
$Title
|
$Title
|
||||||
</button>
|
</button>
|
||||||
|
Loading…
Reference in New Issue
Block a user