mirror of
https://github.com/silverstripe/silverstripe-userforms.git
synced 2024-10-22 17:05:42 +02:00
Add "Add page break" button
Fix unit test failures
This commit is contained in:
parent
0ab7e27970
commit
9f112e3b23
@ -34,12 +34,16 @@ class UserFormFieldEditorExtension extends DataExtension {
|
|||||||
public function getFieldEditorGrid() {
|
public function getFieldEditorGrid() {
|
||||||
$fields = $this->owner->Fields();
|
$fields = $this->owner->Fields();
|
||||||
|
|
||||||
$this->createInitialFormStep();
|
$this->createInitialFormStep(true);
|
||||||
|
|
||||||
$editableColumns = new GridFieldEditableColumns();
|
$editableColumns = new GridFieldEditableColumns();
|
||||||
$editableColumns->setDisplayFields(array(
|
$editableColumns->setDisplayFields(array(
|
||||||
'ClassName' => function($record, $column, $grid) {
|
'ClassName' => function($record, $column, $grid) {
|
||||||
|
if($record instanceof EditableFormStep) {
|
||||||
|
return new LabelField($column, "Page Break");
|
||||||
|
} else {
|
||||||
return DropdownField::create($column, '', $this->getEditableFieldClasses());
|
return DropdownField::create($column, '', $this->getEditableFieldClasses());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'Title' => function($record, $column, $grid) {
|
'Title' => function($record, $column, $grid) {
|
||||||
return TextField::create($column, ' ')
|
return TextField::create($column, ' ')
|
||||||
@ -47,22 +51,28 @@ class UserFormFieldEditorExtension extends DataExtension {
|
|||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
$fieldEditor = GridField::create(
|
$config = GridFieldConfig::create()
|
||||||
'Fields',
|
|
||||||
_t('UserDefinedForm.FIELDS', 'Fields'),
|
|
||||||
$fields,
|
|
||||||
GridFieldConfig::create()
|
|
||||||
->addComponents(
|
->addComponents(
|
||||||
$editableColumns,
|
$editableColumns,
|
||||||
new GridFieldButtonRow(),
|
new GridFieldButtonRow(),
|
||||||
new GridFieldAddNewInlineButton(),
|
$addField = new GridFieldAddNewInlineButton(),
|
||||||
|
$addStep = new GridFieldAddItemInlineButton('EditableFormStep'),
|
||||||
new GridFieldEditButton(),
|
new GridFieldEditButton(),
|
||||||
new GridFieldDeleteAction(),
|
new GridFieldDeleteAction(),
|
||||||
new GridFieldToolbarHeader(),
|
new GridFieldToolbarHeader(),
|
||||||
new GridFieldOrderableRows('Sort'),
|
new GridFieldOrderableRows('Sort'),
|
||||||
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(
|
||||||
|
'Fields',
|
||||||
|
_t('UserDefinedForm.FIELDS', 'Fields'),
|
||||||
|
$fields,
|
||||||
|
$config
|
||||||
);
|
);
|
||||||
|
|
||||||
return $fieldEditor;
|
return $fieldEditor;
|
||||||
@ -72,24 +82,41 @@ class UserFormFieldEditorExtension extends DataExtension {
|
|||||||
* A UserForm must have at least one step.
|
* A UserForm must have at least one step.
|
||||||
* If no steps exist, create an initial step, and put all fields inside it.
|
* If no steps exist, create an initial step, and put all fields inside it.
|
||||||
*
|
*
|
||||||
|
* @param bool $force
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function createInitialFormStep() {
|
public function createInitialFormStep($force = false) {
|
||||||
// If there's already an initial step, do nothing.
|
// Only invoke once saved
|
||||||
if ($this->owner->Fields()->filter('ClassName', 'EditableFormStep')->Count()) {
|
if(!$this->owner->exists()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$step = EditableFormStep::create();
|
// Check if first field is a step
|
||||||
|
$fields = $this->owner->Fields();
|
||||||
|
$firstField = $fields->first();
|
||||||
|
if($firstField instanceof EditableFormStep) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$step->ParentID = $this->owner->ID;
|
// Don't create steps on write if there are no formfields, as this
|
||||||
$step->write();
|
// can create duplicate first steps during publish of new records
|
||||||
|
if(!$force && !$firstField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Assign each field to the initial step.
|
// Re-apply sort to each field starting at 2
|
||||||
foreach ($this->owner->Fields()->exclude('ID', $step->ID) as $field) {
|
$next = 2;
|
||||||
$field->StepID = $step->ID;
|
foreach($fields as $field) {
|
||||||
|
$field->Sort = $next++;
|
||||||
$field->write();
|
$field->write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add step
|
||||||
|
$step = EditableFormStep::create();
|
||||||
|
$step->Title = _t('EditableFormStep.TITLE_FIRST', 'First Step');
|
||||||
|
$step->Sort = 1;
|
||||||
|
$step->write();
|
||||||
|
$fields->add($step);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,6 +146,13 @@ class UserFormFieldEditorExtension extends DataExtension {
|
|||||||
return $editableFieldClasses;
|
return $editableFieldClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that at least one page exists at the start
|
||||||
|
*/
|
||||||
|
public function onAfterWrite() {
|
||||||
|
$this->createInitialFormStep();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SiteTree::doPublish
|
* @see SiteTree::doPublish
|
||||||
* @param Page $original
|
* @param Page $original
|
||||||
|
@ -65,82 +65,42 @@ class UserForm extends Form {
|
|||||||
return $steps;
|
return $steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the form steps.
|
|
||||||
*
|
|
||||||
* @return ArrayList
|
|
||||||
*/
|
|
||||||
public function getFormSteps() {
|
|
||||||
$steps = new ArrayList();
|
|
||||||
|
|
||||||
foreach ($this->controller->Fields() as $field) {
|
|
||||||
if ($field instanceof EditableFormStep) {
|
|
||||||
$steps->push($field->getFormField());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(empty($steps->last())) {
|
|
||||||
trigger_error('Missing first step in form', E_USER_WARNING);
|
|
||||||
$steps->push(CompositeField::create());
|
|
||||||
}
|
|
||||||
|
|
||||||
$steps->last()->push($field->getFormField());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $steps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the form fields for the form on this page. Can modify this FieldSet
|
* Get the form fields for the form on this page. Can modify this FieldSet
|
||||||
* by using {@link updateFormFields()} on an {@link Extension} subclass which
|
* by using {@link updateFormFields()} on an {@link Extension} subclass which
|
||||||
* is applied to this controller.
|
* is applied to this controller.
|
||||||
*
|
*
|
||||||
|
* This will be a list of top level composite steps
|
||||||
|
*
|
||||||
* @return FieldList
|
* @return FieldList
|
||||||
*/
|
*/
|
||||||
public function getFormFields() {
|
public function getFormFields() {
|
||||||
$fields = new FieldList();
|
$fields = new FieldList();
|
||||||
|
$emptyStep = null; // Last empty step, which may or may not later have children
|
||||||
|
|
||||||
foreach($this->controller->Fields() as $editableField) {
|
foreach ($this->controller->Fields() as $field) {
|
||||||
// get the raw form field from the editable version
|
// When we encounter a step, save it
|
||||||
$field = $editableField->getFormField();
|
if ($field instanceof EditableFormStep) {
|
||||||
|
$emptyStep = $field->getFormField();
|
||||||
if(!$field) continue;
|
continue;
|
||||||
|
|
||||||
// set the error / formatting messages
|
|
||||||
$field->setCustomValidationMessage($editableField->getErrorMessage());
|
|
||||||
|
|
||||||
// set the right title on this field
|
|
||||||
if($right = $editableField->RightTitle) {
|
|
||||||
// Since this field expects raw html, safely escape the user data prior
|
|
||||||
$field->setRightTitle(Convert::raw2xml($right));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this field is required add some
|
// Ensure that the last field is a step
|
||||||
if($editableField->Required) {
|
if($emptyStep) {
|
||||||
$field->addExtraClass('requiredField');
|
// When we reach the first non-step field, any empty step will no longer be empty
|
||||||
|
$fields->push($emptyStep);
|
||||||
|
$emptyStep = null;
|
||||||
|
|
||||||
if($identifier = UserDefinedForm::config()->required_identifier) {
|
} elseif(! $fields->last()) {
|
||||||
|
// If no steps have been saved yet, warn
|
||||||
$title = $field->Title() ." <span class='required-identifier'>". $identifier . "</span>";
|
trigger_error('Missing first step in form', E_USER_WARNING);
|
||||||
$field->setTitle($title);
|
$fields->push(singleton('EditableFormStep')->getFormField());
|
||||||
}
|
|
||||||
}
|
|
||||||
// if this field has an extra class
|
|
||||||
if($extraClass = $editableField->ExtraClass) {
|
|
||||||
$field->addExtraClass(Convert::raw2att($extraClass));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the values passed by the url to the field
|
$fields->last()->push($field->getFormField());
|
||||||
$request = $this->controller->getRequest();
|
|
||||||
if($value = $request->getVar($field->getName())) {
|
|
||||||
$field->setValue($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$fields->push($field);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->extend('updateFormFields', $fields);
|
$this->extend('updateFormFields', $fields);
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
246
code/forms/gridfield/GridFieldAddItemInlineButton.php
Normal file
246
code/forms/gridfield/GridFieldAddItemInlineButton.php
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows inline adding of classes with a default type
|
||||||
|
*
|
||||||
|
* Provides an alternative to GridFieldAddNewInlineButton, but allows you to set a classname
|
||||||
|
*/
|
||||||
|
class GridFieldAddItemInlineButton implements GridField_HTMLProvider, GridField_SaveHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment id
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $fragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Button title
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $modelClass = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra CSS classes for this row
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $extraClass = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class Name of class to default to
|
||||||
|
* @param string $fragment The fragment to render the button into
|
||||||
|
*/
|
||||||
|
public function __construct($class, $fragment = 'buttons-before-left') {
|
||||||
|
$this->setClass($class);
|
||||||
|
$this->setFragment($fragment);
|
||||||
|
$this->setTitle(_t('GridFieldExtensions.ADD', 'Add'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the fragment name this button is rendered into.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFragment() {
|
||||||
|
return $this->fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the fragment name this button is rendered into.
|
||||||
|
*
|
||||||
|
* @param string $fragment
|
||||||
|
* @return GridFieldAddNewInlineButton $this
|
||||||
|
*/
|
||||||
|
public function setFragment($fragment) {
|
||||||
|
$this->fragment = $fragment;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the button title text.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTitle() {
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the button title text.
|
||||||
|
*
|
||||||
|
* @param string $title
|
||||||
|
* @return GridFieldAddNewInlineButton $this
|
||||||
|
*/
|
||||||
|
public function setTitle($title) {
|
||||||
|
$this->title = $title;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHTMLFragments($grid) {
|
||||||
|
if($grid->getList() && !singleton($grid->getModelClass())->canCreate()) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$fragment = $this->getFragment();
|
||||||
|
|
||||||
|
if(!$editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns')) {
|
||||||
|
throw new Exception('Inline adding requires the editable columns component');
|
||||||
|
}
|
||||||
|
|
||||||
|
Requirements::javascript(THIRDPARTY_DIR . '/javascript-templates/tmpl.js');
|
||||||
|
GridFieldExtensions::include_requirements();
|
||||||
|
Requirements::javascript(USERFORMS_DIR . '/javascript/GridFieldAddItemInlineButton.js');
|
||||||
|
|
||||||
|
$data = new ArrayData(array(
|
||||||
|
'Title' => $this->getTitle(),
|
||||||
|
'TemplateName' => $this->getRowTemplateName()
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$fragment => $data->renderWith(__CLASS__),
|
||||||
|
'after' => $this->getItemRowTemplate($grid, $editable)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because getRowTemplate is private
|
||||||
|
*
|
||||||
|
* @param GridField $grid
|
||||||
|
* @param GridFieldEditableColumns $editable
|
||||||
|
* @return type
|
||||||
|
*/
|
||||||
|
protected function getItemRowTemplate(GridField $grid, GridFieldEditableColumns $editable) {
|
||||||
|
$columns = new ArrayList();
|
||||||
|
$handled = array_keys($editable->getDisplayFields($grid));
|
||||||
|
|
||||||
|
$record = Object::create($this->getClass());
|
||||||
|
|
||||||
|
$fields = $editable->getFields($grid, $record);
|
||||||
|
|
||||||
|
foreach($grid->getColumns() as $column) {
|
||||||
|
$content = null;
|
||||||
|
if(in_array($column, $handled)) {
|
||||||
|
$field = $fields->dataFieldByName($column);
|
||||||
|
if($field) {
|
||||||
|
$field->setName(sprintf(
|
||||||
|
'%s[%s][%s][{%%=o.num%%}][%s]', $grid->getName(), __CLASS__, $this->getClass(), $field->getName()
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
$field = $fields->fieldByName($column);
|
||||||
|
}
|
||||||
|
if($field) {
|
||||||
|
$content = $field->Field();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$attrs = '';
|
||||||
|
|
||||||
|
foreach($grid->getColumnAttributes($record, $column) as $attr => $val) {
|
||||||
|
$attrs .= sprintf(' %s="%s"', $attr, Convert::raw2att($val));
|
||||||
|
}
|
||||||
|
|
||||||
|
$columns->push(new ArrayData(array(
|
||||||
|
'Content' => $content,
|
||||||
|
'Attributes' => $attrs,
|
||||||
|
'IsActions' => $column == 'Actions'
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = new ArrayData(array(
|
||||||
|
'Columns' => $columns,
|
||||||
|
'ExtraClass' => $this->getExtraClass(),
|
||||||
|
'RecordClass' => $this->getClass(),
|
||||||
|
'TemplateName' => $this->getRowTemplateName()
|
||||||
|
));
|
||||||
|
return $data->renderWith(__CLASS__ . '_Row');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleSave(GridField $grid, DataObjectInterface $record) {
|
||||||
|
$list = $grid->getList();
|
||||||
|
$value = $grid->Value();
|
||||||
|
$class = $this->getClass();
|
||||||
|
|
||||||
|
if(!isset($value[__CLASS__][$class]) || !is_array($value[__CLASS__][$class])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns');
|
||||||
|
$form = $editable->getForm($grid, $record);
|
||||||
|
|
||||||
|
if(!singleton($class)->canCreate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process records matching the specified class
|
||||||
|
foreach($value[__CLASS__][$class] as $fields) {
|
||||||
|
$item = $class::create();
|
||||||
|
$extra = array();
|
||||||
|
|
||||||
|
$form->loadDataFrom($fields, Form::MERGE_CLEAR_MISSING);
|
||||||
|
$form->saveInto($item);
|
||||||
|
|
||||||
|
if($list instanceof ManyManyList) {
|
||||||
|
$extra = array_intersect_key($form->getData(), (array) $list->getExtraFields());
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->write();
|
||||||
|
$list->add($item, $extra);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the class of the object to create
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getClass() {
|
||||||
|
return $this->modelClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the class to create
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
*/
|
||||||
|
public function setClass($class) {
|
||||||
|
$this->modelClass = $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get extra CSS classes for this row
|
||||||
|
*
|
||||||
|
* @return type
|
||||||
|
*/
|
||||||
|
public function getExtraClass() {
|
||||||
|
return $this->extraClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets extra CSS classes for this row
|
||||||
|
*
|
||||||
|
* @param string $extraClass
|
||||||
|
*/
|
||||||
|
public function setExtraClass($extraClass) {
|
||||||
|
$this->extraClass = $extraClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get name of item template
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getRowTemplateName() {
|
||||||
|
return 'ss-gridfield-add-inline-template-' . $this->getClass();
|
||||||
|
}
|
||||||
|
}
|
@ -98,6 +98,7 @@ class UserDefinedForm extends Page {
|
|||||||
* @return FieldList
|
* @return FieldList
|
||||||
*/
|
*/
|
||||||
public function getCMSFields() {
|
public function getCMSFields() {
|
||||||
|
Requirements::css(USERFORMS_DIR . '/css/UserForm_cms.css');
|
||||||
|
|
||||||
$self = $this;
|
$self = $this;
|
||||||
|
|
||||||
@ -365,9 +366,7 @@ class UserDefinedForm_Controller extends Page_Controller {
|
|||||||
*/
|
*/
|
||||||
public function Form() {
|
public function Form() {
|
||||||
$form = UserForm::create($this);
|
$form = UserForm::create($this);
|
||||||
|
|
||||||
$this->generateConditionalJavascript();
|
$this->generateConditionalJavascript();
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,17 +14,15 @@ class EditableCheckboxGroupField extends EditableMultipleOptionField {
|
|||||||
private static $plural_name = "Checkbox Groups";
|
private static $plural_name = "Checkbox Groups";
|
||||||
|
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
$optionSet = $this->Options();
|
$field = new UserFormsCheckboxSetField($this->Name, $this->EscapedTitle, $this->getOptionsMap());
|
||||||
$optionMap = $optionSet->map('EscapedTitle', 'Title');
|
|
||||||
|
|
||||||
$field = new UserFormsCheckboxSetField($this->Name, $this->Title, $optionMap);
|
|
||||||
|
|
||||||
// Set the default checked items
|
// Set the default checked items
|
||||||
$defaultCheckedItems = $optionSet->filter('Default', 1);
|
$defaultCheckedItems = $this->getDefaultOptions();
|
||||||
if ($defaultCheckedItems->count()) {
|
if ($defaultCheckedItems->count()) {
|
||||||
$field->setDefaultItems($defaultCheckedItems->map('EscapedTitle')->keys());
|
$field->setDefaultItems($defaultCheckedItems->map('EscapedTitle')->keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->doUpdateFormField($field);
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,9 @@ class EditableCountryDropdownField extends EditableFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
return CountryDropdownField::create($this->Name, $this->Title);
|
$field = CountryDropdownField::create($this->Name, $this->EscapedTitle);
|
||||||
|
$this->doUpdateFormField($field);
|
||||||
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getValueFromData($data) {
|
public function getValueFromData($data) {
|
||||||
|
@ -43,17 +43,9 @@ class EditableDateField extends EditableFormField {
|
|||||||
$defaultValue = $this->DefaultToToday
|
$defaultValue = $this->DefaultToToday
|
||||||
? SS_Datetime::now()->Format('Y-m-d')
|
? SS_Datetime::now()->Format('Y-m-d')
|
||||||
: $this->Default;
|
: $this->Default;
|
||||||
$field = EditableDateField_FormField::create( $this->Name, $this->Title, $defaultValue);
|
$field = EditableDateField_FormField::create( $this->Name, $this->EscapedTitle, $defaultValue);
|
||||||
$field->setConfig('showcalendar', true);
|
$field->setConfig('showcalendar', true);
|
||||||
|
$this->doUpdateFormField($field);
|
||||||
if ($this->Required) {
|
|
||||||
// Required validation can conflict so add the Required validation messages
|
|
||||||
// as input attributes
|
|
||||||
$errorMessage = $this->getErrorMessage()->HTML();
|
|
||||||
$field->setAttribute('data-rule-required', 'true');
|
|
||||||
$field->setAttribute('data-msg-required', $errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,30 +28,14 @@ class EditableDropdown extends EditableMultipleOptionField {
|
|||||||
* @return DropdownField
|
* @return DropdownField
|
||||||
*/
|
*/
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
$optionSet = $this->Options();
|
$field = DropdownField::create($this->Name, $this->EscapedTitle, $this->getOptionsMap());
|
||||||
$defaultOptions = $optionSet->filter('Default', 1);
|
|
||||||
$options = array();
|
|
||||||
|
|
||||||
if($optionSet) {
|
// Set default
|
||||||
foreach($optionSet as $option) {
|
$defaultOption = $this->getDefaultOptions()->first();
|
||||||
$options[$option->Title] = $option->Title;
|
if($defaultOption) {
|
||||||
|
$field->setValue($defaultOption->EscapedTitle);
|
||||||
}
|
}
|
||||||
}
|
$this->doUpdateFormField($field);
|
||||||
|
|
||||||
$field = DropdownField::create($this->Name, $this->Title, $options);
|
|
||||||
|
|
||||||
if ($this->Required) {
|
|
||||||
// Required validation can conflict so add the Required validation messages
|
|
||||||
// as input attributes
|
|
||||||
$errorMessage = $this->getErrorMessage()->HTML();
|
|
||||||
$field->setAttribute('data-rule-required', 'true');
|
|
||||||
$field->setAttribute('data-msg-required', $errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($defaultOptions->count()) {
|
|
||||||
$field->setValue($defaultOptions->First()->EscapedTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,19 +18,8 @@ class EditableEmailField extends EditableFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
|
$field = EmailField::create($this->Name, $this->EscapedTitle, $this->Default);
|
||||||
$field = EmailField::create($this->Name, $this->Title);
|
$this->doUpdateFormField($field);
|
||||||
|
|
||||||
if ($this->Required) {
|
|
||||||
// Required and Email validation can conflict so add the Required validation messages
|
|
||||||
// as input attributes
|
|
||||||
$errorMessage = $this->getErrorMessage()->HTML();
|
|
||||||
$field->setAttribute('data-rule-required', 'true');
|
|
||||||
$field->setAttribute('data-msg-required', $errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
$field->setValue($this->Default);
|
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ class EditableFileField extends EditableFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
$field = FileField::create($this->Name, $this->Title);
|
$field = FileField::create($this->Name, $this->EscapedTitle);
|
||||||
|
|
||||||
// filter out '' since this would be a regex problem on JS end
|
// filter out '' since this would be a regex problem on JS end
|
||||||
$field->getValidator()->setAllowedExtensions(
|
$field->getValidator()->setAllowedExtensions(
|
||||||
@ -49,13 +49,7 @@ class EditableFileField extends EditableFormField {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->Required) {
|
$this->doUpdateFormField($field);
|
||||||
// Required validation can conflict so add the Required validation messages
|
|
||||||
// as input attributes
|
|
||||||
$errorMessage = $this->getErrorMessage()->HTML();
|
|
||||||
$field->setAttribute('data-rule-required', 'true');
|
|
||||||
$field->setAttribute('data-msg-required', $errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
@ -433,31 +433,13 @@ class EditableFormField extends DataObject {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Title field of the field in the backend of the page
|
|
||||||
*
|
|
||||||
* @return TextField
|
|
||||||
*/
|
|
||||||
public function TitleField() {
|
|
||||||
$label = _t('EditableFormField.ENTERQUESTION', 'Enter Question');
|
|
||||||
|
|
||||||
$field = new TextField('Title', $label, $this->getField('Title'));
|
|
||||||
$field->setName($this->getFieldName('Title'));
|
|
||||||
|
|
||||||
if(!$this->canEdit()) {
|
|
||||||
return $field->performReadonlyTransformation();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $field;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Title for rendering in the front-end (with XML values escaped)
|
* Returns the Title for rendering in the front-end (with XML values escaped)
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getTitle() {
|
public function getEscapedTitle() {
|
||||||
return Convert::raw2att($this->getField('Title'));
|
return Convert::raw2xml($this->Title);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -497,7 +479,7 @@ class EditableFormField extends DataObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a FormField to appear on the front end. Implement on
|
* Return a FormField to appear on the front end. Implement on
|
||||||
* your subclass
|
* your subclass.
|
||||||
*
|
*
|
||||||
* @return FormField
|
* @return FormField
|
||||||
*/
|
*/
|
||||||
@ -505,6 +487,52 @@ class EditableFormField extends DataObject {
|
|||||||
user_error("Please implement a getFormField() on your EditableFormClass ". $this->ClassName, E_USER_ERROR);
|
user_error("Please implement a getFormField() on your EditableFormClass ". $this->ClassName, E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a formfield with extensions
|
||||||
|
*
|
||||||
|
* @param FormField $field
|
||||||
|
*/
|
||||||
|
public function doUpdateFormField($field) {
|
||||||
|
$this->extend('beforeUpdateFormField', $field);
|
||||||
|
$this->updateFormField($field);
|
||||||
|
$this->extend('afterUpdateFormField', $field);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a formfield with the additional metadata specified by this field
|
||||||
|
*
|
||||||
|
* @param FormField $field
|
||||||
|
*/
|
||||||
|
protected function updateFormField($field) {
|
||||||
|
// set the error / formatting messages
|
||||||
|
$field->setCustomValidationMessage($this->getErrorMessage());
|
||||||
|
|
||||||
|
// set the right title on this field
|
||||||
|
if($this->RightTitle) {
|
||||||
|
// Since this field expects raw html, safely escape the user data prior
|
||||||
|
$field->setRightTitle(Convert::raw2xml($this->RightTitle));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this field is required add some
|
||||||
|
if($this->Required) {
|
||||||
|
// Required validation can conflict so add the Required validation messages as input attributes
|
||||||
|
$errorMessage = $this->getErrorMessage()->HTML();
|
||||||
|
$field->addExtraClass('requiredField');
|
||||||
|
$field->setAttribute('data-rule-required', 'true');
|
||||||
|
$field->setAttribute('data-msg-required', $errorMessage);
|
||||||
|
|
||||||
|
if($identifier = UserDefinedForm::config()->required_identifier) {
|
||||||
|
$title = $field->Title() . " <span class='required-identifier'>". $identifier . "</span>";
|
||||||
|
$field->setTitle($title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this field has an extra class
|
||||||
|
if($field->ExtraClass) {
|
||||||
|
$field->addExtraClass($field->ExtraClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the instance of the submission field class
|
* Return the instance of the submission field class
|
||||||
*
|
*
|
||||||
|
@ -55,11 +55,24 @@ class EditableFormHeading extends EditableFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
$labelField = new HeaderField($this->Name, $this->Title, $this->Level);
|
$labelField = new HeaderField($this->Name, $this->EscapedTitle, $this->Level);
|
||||||
$labelField->addExtraClass('FormHeading');
|
$labelField->addExtraClass('FormHeading');
|
||||||
|
$this->doUpdateFormField($labelField);
|
||||||
return $labelField;
|
return $labelField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function updateFormField($field) {
|
||||||
|
// set the right title on this field
|
||||||
|
if($this->RightTitle) {
|
||||||
|
// Since this field expects raw html, safely escape the user data prior
|
||||||
|
$field->setRightTitle(Convert::raw2xml($this->RightTitle));
|
||||||
|
}
|
||||||
|
// if this field has an extra class
|
||||||
|
if($field->ExtraClass) {
|
||||||
|
$field->addExtraClass($field->ExtraClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function showInReports() {
|
public function showInReports() {
|
||||||
return !$this->HideFromReports;
|
return !$this->HideFromReports;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ class EditableFormStep extends EditableFormField {
|
|||||||
$fields = parent::getCMSFields();
|
$fields = parent::getCMSFields();
|
||||||
|
|
||||||
$fields->removeByName('MergeField');
|
$fields->removeByName('MergeField');
|
||||||
$fields->removeByName('StepID');
|
|
||||||
$fields->removeByName('Default');
|
$fields->removeByName('Default');
|
||||||
$fields->removeByName('Validation');
|
$fields->removeByName('Validation');
|
||||||
$fields->removeByName('CustomRules');
|
$fields->removeByName('CustomRules');
|
||||||
@ -37,7 +36,17 @@ class EditableFormStep extends EditableFormField {
|
|||||||
* @return FormField
|
* @return FormField
|
||||||
*/
|
*/
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
return CompositeField::create()->setTitle($this->Title);
|
$field = CompositeField::create()
|
||||||
|
->setTitle($this->EscapedTitle);
|
||||||
|
$this->doUpdateFormField($field);
|
||||||
|
return $field;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function updateFormField($field) {
|
||||||
|
// if this field has an extra class
|
||||||
|
if($field->ExtraClass) {
|
||||||
|
$field->addExtraClass($field->ExtraClass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,12 +103,16 @@ class EditableLiteralField extends EditableFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
$label = $this->Title
|
// Build label and css classes
|
||||||
? "<label class='left'>".Convert::raw2xml($this->Title)."</label>"
|
$label = '';
|
||||||
: "";
|
$classes = $this->ExtraClass;
|
||||||
$classes = $this->Title ? "" : " nolabel";
|
if(empty($this->Title)) {
|
||||||
|
$classes .= " nolabel";
|
||||||
|
} else {
|
||||||
|
$label = "<label class='left'>{$this->EscapedTitle}</label>";
|
||||||
|
}
|
||||||
|
|
||||||
return new LiteralField(
|
$field = new LiteralField(
|
||||||
"LiteralField[{$this->ID}]",
|
"LiteralField[{$this->ID}]",
|
||||||
sprintf(
|
sprintf(
|
||||||
"<div id='%s' class='field text%s'>
|
"<div id='%s' class='field text%s'>
|
||||||
@ -121,6 +125,9 @@ class EditableLiteralField extends EditableFormField {
|
|||||||
$this->Content
|
$this->Content
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// When dealing with literal fields there is no further customisation that can be added at this point
|
||||||
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showInReports() {
|
public function showInReports() {
|
||||||
|
@ -42,7 +42,9 @@ class EditableMemberListField extends EditableFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$members = Member::map_in_groups($this->GroupID);
|
$members = Member::map_in_groups($this->GroupID);
|
||||||
return new DropdownField($this->Name, $this->Title, $members);
|
$field = new DropdownField($this->Name, $this->EscapedTitle, $members);
|
||||||
|
$this->doUpdateFormField($field);
|
||||||
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getValueFromData($data) {
|
public function getValueFromData($data) {
|
||||||
|
@ -156,11 +156,25 @@ class EditableMultipleOptionField extends EditableFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the form field for this object in the front end form view
|
* Gets map of field options suitable for use in a form
|
||||||
*
|
*
|
||||||
* @return FormField
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getFormField() {
|
protected function getOptionsMap() {
|
||||||
return user_error('Please implement getFormField() on '. $this->class, E_USER_ERROR);
|
$optionSet = $this->Options();
|
||||||
|
$optionMap = $optionSet->map('EscapedTitle', 'Title');
|
||||||
|
if($optionMap instanceof SS_Map) {
|
||||||
|
return $optionMap->toArray();
|
||||||
|
}
|
||||||
|
return $optionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all default options
|
||||||
|
*
|
||||||
|
* @return SS_List
|
||||||
|
*/
|
||||||
|
protected function getDefaultOptions() {
|
||||||
|
return $this->Options()->filter('Default', 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,18 +26,9 @@ class EditableNumericField extends EditableFormField {
|
|||||||
* @return NumericField
|
* @return NumericField
|
||||||
*/
|
*/
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
$field = new NumericField($this->Name, $this->Title);
|
$field = new NumericField($this->Name, $this->EscapedTitle, $this->Default);
|
||||||
$field->addExtraClass('number');
|
$field->addExtraClass('number');
|
||||||
$field->setValue($this->Default);
|
$this->doUpdateFormField($field);
|
||||||
|
|
||||||
if ($this->Required) {
|
|
||||||
// Required and numeric validation can conflict so add the
|
|
||||||
// required validation messages as input attributes
|
|
||||||
$errorMessage = $this->getErrorMessage()->HTML();
|
|
||||||
$field->setAttribute('data-rule-required', 'true');
|
|
||||||
$field->setAttribute('data-msg-required', $errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,39 +49,6 @@ class EditableOption extends DataObject {
|
|||||||
return ($this->Parent()->canDelete($member));
|
return ($this->Parent()->canDelete($member));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Template for the editing view of this option field
|
|
||||||
*/
|
|
||||||
public function EditSegment() {
|
|
||||||
return $this->renderWith('EditableOption');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Title Field for this object
|
|
||||||
*
|
|
||||||
* @return FormField
|
|
||||||
*/
|
|
||||||
public function TitleField() {
|
|
||||||
return new TextField("Fields[{$this->ParentID}][{$this->ID}][Title]", null, $this->Title );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of this field in the form
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public function FieldName() {
|
|
||||||
return "Fields[{$this->ParentID}][{$this->ID}]";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make this option readonly
|
|
||||||
*/
|
|
||||||
public function ReadonlyOption() {
|
|
||||||
$this->readonly = true;
|
|
||||||
return $this->EditSegment();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEscapedTitle() {
|
public function getEscapedTitle() {
|
||||||
return Convert::raw2att($this->Title);
|
return Convert::raw2att($this->Title);
|
||||||
}
|
}
|
||||||
|
@ -25,22 +25,14 @@ class EditableRadioField extends EditableMultipleOptionField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
$optionSet = $this->Options();
|
$field = OptionsetField::create($this->Name, $this->EscapedTitle, $this->getOptionsMap());
|
||||||
$defaultOptions = $optionSet->filter('Default', 1);
|
|
||||||
$options = array();
|
|
||||||
|
|
||||||
if($optionSet) {
|
// Set default item
|
||||||
foreach($optionSet as $option) {
|
$defaultOption = $this->getDefaultOptions()->first();
|
||||||
$options[$option->EscapedTitle] = $option->Title;
|
if($defaultOption) {
|
||||||
|
$field->setValue($defaultOption->EscapedTitle);
|
||||||
}
|
}
|
||||||
}
|
$this->doUpdateFormField($field);
|
||||||
|
|
||||||
$field = OptionsetField::create($this->Name, $this->Title, $options);
|
|
||||||
|
|
||||||
if($defaultOptions->count()) {
|
|
||||||
$field->setValue($defaultOptions->First()->EscapedTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,22 +65,12 @@ class EditableTextField extends EditableFormField {
|
|||||||
*/
|
*/
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
if($this->Rows > 1) {
|
if($this->Rows > 1) {
|
||||||
$field = TextareaField::create($this->Name, $this->Title);
|
$field = TextareaField::create($this->Name, $this->EscapedTitle, $this->Default);
|
||||||
$field->setRows($this->Rows);
|
$field->setRows($this->Rows);
|
||||||
} else {
|
} else {
|
||||||
$field = TextField::create($this->Name, $this->Title, null, $this->MaxLength);
|
$field = TextField::create($this->Name, $this->EscapedTitle, $this->Default, $this->MaxLength);
|
||||||
}
|
}
|
||||||
|
$this->doUpdateFormField($field);
|
||||||
if ($this->Required) {
|
|
||||||
// Required validation can conflict so add the Required validation messages
|
|
||||||
// as input attributes
|
|
||||||
$errorMessage = $this->getErrorMessage()->HTML();
|
|
||||||
$field->setAttribute('data-rule-required', 'true');
|
|
||||||
$field->setAttribute('data-msg-required', $errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
$field->setValue($this->Default);
|
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,16 +32,8 @@ class EditableCheckbox extends EditableFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getFormField() {
|
public function getFormField() {
|
||||||
$field = CheckboxField::create($this->Name, $this->Title, $this->CheckedDefault);
|
$field = CheckboxField::create($this->Name, $this->EscapedTitle, $this->CheckedDefault);
|
||||||
|
$this->doUpdateFormField($field);
|
||||||
if ($this->Required) {
|
|
||||||
// Required validation can conflict so add the Required validation messages
|
|
||||||
// as input attributes
|
|
||||||
$errorMessage = $this->getErrorMessage()->HTML();
|
|
||||||
$field->setAttribute('data-rule-required', 'true');
|
|
||||||
$field->setAttribute('data-msg-required', $errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
css/UserForm_cms.css
Normal file
24
css/UserForm_cms.css
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
.cms .ss-gridfield > div.ss-gridfield-buttonrow-before {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Styles for page steps
|
||||||
|
*/
|
||||||
|
.cms table.ss-gridfield-table .ss-gridfield-inline-new.uf-gridfield-steprow,
|
||||||
|
.cms table.ss-gridfield-table .ss-gridfield-item[data-class='EditableFormStep'],
|
||||||
|
.cms table.ss-gridfield-table .ss-gridfield-inline-new.uf-gridfield-steprow:hover,
|
||||||
|
.cms table.ss-gridfield-table .ss-gridfield-item[data-class='EditableFormStep']:hover
|
||||||
|
{
|
||||||
|
background: #dae2e7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cms table.ss-gridfield-table .ss-gridfield-inline-new.uf-gridfield-steprow label,
|
||||||
|
.cms table.ss-gridfield-table .ss-gridfield-item[data-class='EditableFormStep'] label
|
||||||
|
{
|
||||||
|
font-weight: bold;
|
||||||
|
color: #393939;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
41
javascript/GridFieldAddItemInlineButton.js
Normal file
41
javascript/GridFieldAddItemInlineButton.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
(function($) {
|
||||||
|
$.entwine("ss", function($) {
|
||||||
|
// See gridfieldextensions/javascript/GridFieldExtensions.js
|
||||||
|
|
||||||
|
$(".ss-gridfield.ss-gridfield-editable").entwine({
|
||||||
|
onaddnewiteminline: function(e, template) {
|
||||||
|
var tmpl = window.tmpl;
|
||||||
|
var row = this.find("." + template);
|
||||||
|
var num = this.data("add-inline-num") || 1;
|
||||||
|
|
||||||
|
tmpl.cache[template] = tmpl(row.html());
|
||||||
|
|
||||||
|
this.find("tbody").append(tmpl(template, { num: num }));
|
||||||
|
this.find(".ss-gridfield-no-items").hide();
|
||||||
|
this.data("add-inline-num", num + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".ss-gridfield-add-new-item-inline").entwine({
|
||||||
|
onclick: function() {
|
||||||
|
// Get custom class from button
|
||||||
|
var template = this.data('template');
|
||||||
|
this.getGridField().trigger("addnewiteminline", template);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
@ -11,7 +11,7 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<% if $Legend %><legend>$Legend</legend><% end_if %>
|
<% if $Legend %><legend>$Legend</legend><% end_if %>
|
||||||
|
|
||||||
<% loop $FormSteps %>
|
<% if $FormFields%><% loop $FormFields %>
|
||||||
<fieldset class="form-step">
|
<fieldset class="form-step">
|
||||||
<% if $Top.DisplayErrorMessagesAtTop %>
|
<% if $Top.DisplayErrorMessagesAtTop %>
|
||||||
<fieldset class="error-container" aria-hidden="true" style="display: none;">
|
<fieldset class="error-container" aria-hidden="true" style="display: none;">
|
||||||
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<% include UserFormStepNav ContainingPage=$Top %>
|
<% include UserFormStepNav ContainingPage=$Top %>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<% end_loop %>
|
<% end_loop %><% end_if %>
|
||||||
|
|
||||||
<div class="clear"><!-- --></div>
|
<div class="clear"><!-- --></div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
3
templates/gridfield/GridFieldAddItemInlineButton.ss
Normal file
3
templates/gridfield/GridFieldAddItemInlineButton.ss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<button href="$Link" class="ss-gridfield-add-new-item-inline ss-ui-button" data-icon="add" data-template="$TemplateName.ATT">
|
||||||
|
$Title
|
||||||
|
</button>
|
13
templates/gridfield/GridFieldAddItemInlineButton_Row.ss
Normal file
13
templates/gridfield/GridFieldAddItemInlineButton_Row.ss
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script type="text/x-tmpl" class="$TemplateName">
|
||||||
|
<tr class="ss-gridfield-inline-new $ExtraClass.ATT">
|
||||||
|
<% loop $Columns %>
|
||||||
|
<% if $IsActions %>
|
||||||
|
<td$Attributes>
|
||||||
|
<button class="ss-gridfield-delete-inline gridfield-button-delete ss-ui-button" data-icon="cross-circle"></button>
|
||||||
|
</td>
|
||||||
|
<% else %>
|
||||||
|
<td$Attributes>$Content</td>
|
||||||
|
<% end_if %>
|
||||||
|
<% end_loop %>
|
||||||
|
</tr>
|
||||||
|
</script>
|
@ -80,27 +80,6 @@ class EditableFormFieldTest extends FunctionalTest {
|
|||||||
$this->assertEquals(array('Option 5' => 'Option 5', 'Option 6' => 'Option 6'), $values);
|
$this->assertEquals(array('Option 5' => 'Option 5', 'Option 6' => 'Option 6'), $values);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testTitleField() {
|
|
||||||
$text = $this->objFromFixture('EditableTextField', 'basic-text');
|
|
||||||
$this->logInWithPermission('ADMIN');
|
|
||||||
|
|
||||||
$title = $text->TitleField();
|
|
||||||
|
|
||||||
$this->assertThat($title, $this->isInstanceOf('TextField'));
|
|
||||||
$this->assertEquals($title->Title(), "Enter Question");
|
|
||||||
$this->assertEquals($title->Value(), "Basic Text Field");
|
|
||||||
|
|
||||||
$member = Member::currentUser();
|
|
||||||
$member->logOut();
|
|
||||||
|
|
||||||
// read only version
|
|
||||||
$title = $text->TitleField();
|
|
||||||
|
|
||||||
$this->assertThat($title, $this->isInstanceOf('ReadonlyField'));
|
|
||||||
$this->assertEquals($title->Title(), "Enter Question");
|
|
||||||
$this->assertEquals($title->Value(), "Basic Text Field");
|
|
||||||
}
|
|
||||||
|
|
||||||
function testMultipleOptionDuplication() {
|
function testMultipleOptionDuplication() {
|
||||||
$dropdown = $this->objFromFixture('EditableDropdown','basic-dropdown');
|
$dropdown = $this->objFromFixture('EditableDropdown','basic-dropdown');
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
class UserDefinedFormControllerTest extends FunctionalTest {
|
class UserDefinedFormControllerTest extends FunctionalTest {
|
||||||
|
|
||||||
static $fixture_file = 'userforms/tests/UserDefinedFormTest.yml';
|
static $fixture_file = 'UserDefinedFormTest.yml';
|
||||||
|
|
||||||
function testProcess() {
|
function testProcess() {
|
||||||
$form = $this->setupFormFrontend();
|
$form = $this->setupFormFrontend();
|
||||||
@ -106,9 +106,11 @@ class UserDefinedFormControllerTest extends FunctionalTest {
|
|||||||
|
|
||||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||||
|
|
||||||
$fields = $controller->Form()->getFormFields();
|
$formSteps = $controller->Form()->getFormFields();
|
||||||
|
$firstStep = $formSteps->first();
|
||||||
|
|
||||||
$this->assertEquals($fields->Count(), 1);
|
$this->assertEquals($formSteps->Count(), 1);
|
||||||
|
$this->assertEquals($firstStep->getChildren()->Count(), 1);
|
||||||
|
|
||||||
// custom error message on a form field
|
// custom error message on a form field
|
||||||
$requiredForm = $this->objFromFixture('UserDefinedForm', 'validation-form');
|
$requiredForm = $this->objFromFixture('UserDefinedForm', 'validation-form');
|
||||||
@ -116,20 +118,23 @@ class UserDefinedFormControllerTest extends FunctionalTest {
|
|||||||
|
|
||||||
UserDefinedForm::config()->required_identifier = "*";
|
UserDefinedForm::config()->required_identifier = "*";
|
||||||
|
|
||||||
$fields = $controller->Form()->getFormFields();
|
$formSteps = $controller->Form()->getFormFields();
|
||||||
|
$firstStep = $formSteps->first();
|
||||||
|
$firstField = $firstStep->getChildren()->first();
|
||||||
|
|
||||||
$this->assertEquals($fields->First()->getCustomValidationMessage()->getValue(), 'Custom Error Message');
|
$this->assertEquals('Custom Error Message', $firstField->getCustomValidationMessage()->getValue());
|
||||||
$this->assertEquals($fields->First()->Title(), 'Required Text Field <span class=\'required-identifier\'>*</span>');
|
$this->assertEquals($firstField->Title(), 'Required Text Field <span class=\'required-identifier\'>*</span>');
|
||||||
|
|
||||||
// test custom right title
|
// test custom right title
|
||||||
$field = $form->Fields()->First();
|
$field = $form->Fields()->limit(1, 1)->First();
|
||||||
$field->RightTitle = 'Right Title';
|
$field->RightTitle = 'Right Title';
|
||||||
$field->write();
|
$field->write();
|
||||||
|
|
||||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||||
$fields = $controller->Form()->getFormFields();
|
$formSteps = $controller->Form()->getFormFields();
|
||||||
|
$firstStep = $formSteps->first();
|
||||||
|
|
||||||
$this->assertEquals($fields->First()->RightTitle(), "Right Title");
|
$this->assertEquals($firstStep->getChildren()->First()->RightTitle(), "Right Title");
|
||||||
|
|
||||||
// test empty form
|
// test empty form
|
||||||
$emptyForm = $this->objFromFixture('UserDefinedForm', 'empty-form');
|
$emptyForm = $this->objFromFixture('UserDefinedForm', 'empty-form');
|
||||||
|
@ -3,13 +3,11 @@
|
|||||||
/**
|
/**
|
||||||
* @package userforms
|
* @package userforms
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class UserDefinedFormTest extends FunctionalTest {
|
class UserDefinedFormTest extends FunctionalTest {
|
||||||
|
|
||||||
static $fixture_file = 'UserDefinedFormTest.yml';
|
static $fixture_file = 'UserDefinedFormTest.yml';
|
||||||
|
|
||||||
|
public function testRollbackToVersion() {
|
||||||
function testRollbackToVersion() {
|
|
||||||
$this->markTestSkipped(
|
$this->markTestSkipped(
|
||||||
'UserDefinedForm::rollback() has not been implemented completely'
|
'UserDefinedForm::rollback() has not been implemented completely'
|
||||||
);
|
);
|
||||||
@ -37,7 +35,7 @@ class UserDefinedFormTest extends FunctionalTest {
|
|||||||
$this->assertEquals($orignal->SubmitButtonText, 'Button Text');
|
$this->assertEquals($orignal->SubmitButtonText, 'Button Text');
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetCMSFields() {
|
public function testGetCMSFields() {
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||||
|
|
||||||
@ -49,7 +47,7 @@ class UserDefinedFormTest extends FunctionalTest {
|
|||||||
$this->assertTrue($fields->dataFieldByName('OnCompleteMessage') != null);
|
$this->assertTrue($fields->dataFieldByName('OnCompleteMessage') != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testEmailRecipientPopup() {
|
public function testEmailRecipientPopup() {
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||||
@ -160,13 +158,13 @@ class UserDefinedFormTest extends FunctionalTest {
|
|||||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||||
|
|
||||||
$this->assertNotNull($live);
|
$this->assertNotNull($live);
|
||||||
$this->assertEquals($live->Fields()->Count(), 1);
|
$this->assertEquals(2, $live->Fields()->Count()); // one page and one field
|
||||||
|
|
||||||
$dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown');
|
$dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown');
|
||||||
$form->Fields()->add($dropdown);
|
$form->Fields()->add($dropdown);
|
||||||
|
|
||||||
$stage = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = $form->ID");
|
$stage = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = $form->ID");
|
||||||
$this->assertEquals($stage->Fields()->Count(), 2);
|
$this->assertEquals(3, $stage->Fields()->Count());
|
||||||
|
|
||||||
// should not have published the dropdown
|
// should not have published the dropdown
|
||||||
$liveDropdown = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $dropdown->ID");
|
$liveDropdown = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $dropdown->ID");
|
||||||
@ -176,11 +174,10 @@ class UserDefinedFormTest extends FunctionalTest {
|
|||||||
$form->doPublish();
|
$form->doPublish();
|
||||||
|
|
||||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||||
$this->assertEquals($live->Fields()->Count(), 2);
|
$this->assertEquals(3, $live->Fields()->Count());
|
||||||
|
|
||||||
// edit the title
|
// edit the title
|
||||||
$text = $form->Fields()->First();
|
$text = $form->Fields()->limit(1, 1)->First();
|
||||||
|
|
||||||
$text->Title = 'Edited title';
|
$text->Title = 'Edited title';
|
||||||
$text->write();
|
$text->write();
|
||||||
|
|
||||||
@ -197,21 +194,20 @@ class UserDefinedFormTest extends FunctionalTest {
|
|||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||||
$form->write();
|
$form->write();
|
||||||
|
$this->assertEquals(0, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||||
$form->doPublish();
|
$form->doPublish();
|
||||||
|
|
||||||
// assert that it exists and has a field
|
// assert that it exists and has a field
|
||||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||||
|
|
||||||
$this->assertTrue(isset($live));
|
$this->assertTrue(isset($live));
|
||||||
$this->assertEquals(DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value(), 1);
|
$this->assertEquals(2, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||||
|
|
||||||
// unpublish
|
// unpublish
|
||||||
$form->doUnpublish();
|
$form->doUnpublish();
|
||||||
|
|
||||||
$this->assertNull(Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID"));
|
$this->assertNull(Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID"));
|
||||||
$this->assertEquals(DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value(), 0);
|
$this->assertEquals(0, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDoRevertToLive() {
|
function testDoRevertToLive() {
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
EditableFormStep:
|
||||||
|
form1step1:
|
||||||
|
Title: 'Step 1'
|
||||||
|
form3step1:
|
||||||
|
Title: 'Step 1'
|
||||||
|
form4step1:
|
||||||
|
Title: 'Step 1'
|
||||||
|
form5step1:
|
||||||
|
Title: 'Step 1'
|
||||||
|
|
||||||
EditableOption:
|
EditableOption:
|
||||||
option-1:
|
option-1:
|
||||||
Name: Option1
|
Name: Option1
|
||||||
@ -183,7 +193,7 @@ UserDefinedForm_EmailRecipient:
|
|||||||
UserDefinedForm:
|
UserDefinedForm:
|
||||||
basic-form-page:
|
basic-form-page:
|
||||||
Title: User Defined Form
|
Title: User Defined Form
|
||||||
Fields: =>EditableTextField.basic-text
|
Fields: =>EditableFormStep.form1step1,=>EditableTextField.basic-text
|
||||||
EmailRecipients: =>UserDefinedForm_EmailRecipient.recipient-1, =>UserDefinedForm_EmailRecipient.no-html, =>UserDefinedForm_EmailRecipient.no-data
|
EmailRecipients: =>UserDefinedForm_EmailRecipient.recipient-1, =>UserDefinedForm_EmailRecipient.no-html, =>UserDefinedForm_EmailRecipient.no-data
|
||||||
|
|
||||||
form-with-reset-and-custom-action:
|
form-with-reset-and-custom-action:
|
||||||
@ -193,15 +203,15 @@ UserDefinedForm:
|
|||||||
|
|
||||||
validation-form:
|
validation-form:
|
||||||
Title: Validation Form
|
Title: Validation Form
|
||||||
Fields: =>EditableTextField.required-text
|
Fields: =>EditableFormStep.form3step1,=>EditableTextField.required-text
|
||||||
|
|
||||||
custom-rules-form:
|
custom-rules-form:
|
||||||
Title: Custom Rules Form
|
Title: Custom Rules Form
|
||||||
Fields: =>EditableCheckbox.checkbox-2, =>EditableTextField.basic-text-2
|
Fields: =>EditableFormStep.form4step1,=>EditableCheckbox.checkbox-2, =>EditableTextField.basic-text-2
|
||||||
empty-form:
|
empty-form:
|
||||||
Title: Empty Form
|
Title: Empty Form
|
||||||
|
|
||||||
filtered-form-page:
|
filtered-form-page:
|
||||||
Title: 'Page with filtered recipients'
|
Title: 'Page with filtered recipients'
|
||||||
Fields: =>EditableCheckboxGroupField.checkbox-group, =>EditableTextField.your-name-field, =>EditableTextField.street-field, =>EditableTextField.city-field
|
Fields: =>EditableFormStep.form5step1,=>EditableCheckboxGroupField.checkbox-group, =>EditableTextField.your-name-field, =>EditableTextField.street-field, =>EditableTextField.city-field
|
||||||
EmailRecipients: =>UserDefinedForm_EmailRecipient.unfiltered-recipient-1, =>UserDefinedForm_EmailRecipient.filtered-recipient-1, =>UserDefinedForm_EmailRecipient.filtered-recipient-2
|
EmailRecipients: =>UserDefinedForm_EmailRecipient.unfiltered-recipient-1, =>UserDefinedForm_EmailRecipient.filtered-recipient-1, =>UserDefinedForm_EmailRecipient.filtered-recipient-2
|
||||||
|
Loading…
Reference in New Issue
Block a user