ENHANCEMENT: implemented tests for exporting csv files

This commit is contained in:
Will Rossiter 2010-09-08 10:35:43 +00:00
parent 99d4721c88
commit 503c5c3ff6
9 changed files with 368 additions and 148 deletions

View File

@ -13,7 +13,7 @@ class SubmittedForm extends DataObject {
); );
static $has_many = array( static $has_many = array(
"FieldValues" => "SubmittedFormField" "Values" => "SubmittedFormField"
); );
/** /**
@ -22,11 +22,13 @@ class SubmittedForm extends DataObject {
* *
*/ */
protected function onBeforeDelete() { protected function onBeforeDelete() {
if($this->FieldValues()) {
foreach($this->FieldValues() as $value) { if($this->Values()) {
foreach($this->Values() as $value) {
$value->delete(); $value->delete();
} }
} }
parent::onBeforeDelete(); parent::onBeforeDelete();
} }
} }

View File

@ -61,19 +61,34 @@ class SubmittedFormReportField extends FormField {
* *
* @return HTTPResponse / bool * @return HTTPResponse / bool
*/ */
public function export() { public function export($id = false) {
if($id && is_int($id)) {
$SQL_ID = $id;
}
else {
if(isset($_REQUEST['id'])) {
$SQL_ID = Convert::raw2sql($_REQUEST['id']);
}
else {
user_error("No UserDefinedForm Defined.", E_USER_ERROR);
return false;
}
}
$now = Date("Y-m-d_h.i.s"); $now = Date("Y-m-d_h.i.s");
$fileName = "export-$now.csv"; $fileName = "export-$now.csv";
$separator = ","; $separator = ",";
// Get the UserDefinedForm to export data from the URL
$SQL_ID = (isset($_REQUEST['id'])) ? Convert::raw2sql($_REQUEST['id']) : false;
if($SQL_ID) {
$udf = DataObject::get_by_id("UserDefinedForm", $SQL_ID); $udf = DataObject::get_by_id("UserDefinedForm", $SQL_ID);
if($udf) { if($udf) {
$csvHeaderNames = array();
$csvHeaderTitle = array();
$submissions = $udf->Submissions(); $submissions = $udf->Submissions();
if($submissions && $submissions->Count() > 0) {
if($submissions && $submissions->exists()) {
// Get all the submission IDs (so we know what names/titles to get - helps for sites with many UDF's) // Get all the submission IDs (so we know what names/titles to get - helps for sites with many UDF's)
$inClause = array(); $inClause = array();
@ -83,18 +98,19 @@ class SubmittedFormReportField extends FormField {
// Get the CSV header rows from the database // Get the CSV header rows from the database
$tmp = DB::query("SELECT DISTINCT \"SubmittedFormField\".\"ID\", \"Name\", \"Title\" $tmp = DB::query("
SELECT DISTINCT \"SubmittedFormField\".\"ID\", \"Name\", \"Title\"
FROM \"SubmittedFormField\" FROM \"SubmittedFormField\"
LEFT JOIN \"SubmittedForm\" ON \"SubmittedForm\".\"ID\" = \"SubmittedFormField\".\"ParentID\" LEFT JOIN \"SubmittedForm\" ON \"SubmittedForm\".\"ID\" = \"SubmittedFormField\".\"ParentID\"
WHERE \"SubmittedFormField\".\"ParentID\" IN (" . implode(',', $inClause) . ") WHERE \"SubmittedFormField\".\"ParentID\" IN (" . implode(',', $inClause) . ")
GROUP BY \"Name\" GROUP BY \"Name\"
ORDER BY \"SubmittedFormField\".\"ID\""); ORDER BY \"SubmittedFormField\".\"ID\"
");
// Sort the Names and Titles from the database query into separate keyed arrays // Sort the Names and Titles from the database query into separate keyed arrays
foreach($tmp as $array) { foreach($tmp as $array) {
$csvHeaderNames[] = $array['Name']; $csvHeaderNames[] = $array['Name'];
$csvHeaderTitle[] = $array['Title']; $csvHeaderTitle[] = $array['Title'];
} }
// For every submission... // For every submission...
@ -102,60 +118,60 @@ class SubmittedFormReportField extends FormField {
foreach($submissions as $submission) { foreach($submissions as $submission) {
// Get the rows for this submission (One row = one form field) // Get the rows for this submission (One row = one form field)
$dataRow = $submission->FieldValues(); $dataRow = $submission->Values();
$rows[$i] = array(); $rows[$i] = array();
// For every row/field, get all the columns // For every row/field, get all the columns
foreach($dataRow as $column) { foreach($dataRow as $column) {
// If the Name of this field is in the $csvHeaderNames array, get an array of all the places it exists // If the Name of this field is in the $csvHeaderNames array, get an array of all the places it exists
if($index = array_keys($csvHeaderNames, $column->Name)) { if($index = array_keys($csvHeaderNames, $column->Name)) {
if(is_array($index)) { if(is_array($index)) {
// Set the final output array for each index that we want to insert this value into // Set the final output array for each index that we want to insert this value into
foreach($index as $idx) { foreach($index as $idx) {
$rows[$i][$idx] = $column->Value; $rows[$i][$idx] = $column->Value;
} }
$rows[$i]['Submitted'] = $submission->Created;
} }
} }
} }
$rows[$i]['Submitted'] = $submission->Created;
$i++; $i++;
} }
// CSV header row // CSV header row
$csvData = '"' . implode('","', $csvHeaderTitle) . '"' . ',"Submitted"'."\n"; $csvData = '"' . implode('","', $csvHeaderTitle) . '"' . ',"Submitted"'."\n";
// For every row of data (one form submission = one row) // For every row of data (one form submission = one row)
foreach($rows as $row) { foreach($rows as $row) {
// Loop over all the names we can use
for($i=0;$i<count($csvHeaderNames);$i++) { for($i=0;$i<count($csvHeaderNames);$i++) {
if(!isset($row[$i]) || !$row[$i]) $csvData .= '"",'; // If there is no data for this column, output it as blank instead if(!isset($row[$i]) || !$row[$i]) $csvData .= '"",'; // If there is no data for this column, output it as blank instead
else { else {
$tmp = str_replace('"', '""', $row[$i]); $tmp = str_replace('"', '""', $row[$i]);
$csvData .= '"' . $tmp . '",'; $csvData .= '"' . $tmp . '",';
} }
} }
// Start a new row for each submission (re-check we have 'Submitted' in this entry) // Start a new row for each submission (re-check we have 'Submitted' in this entry)
if(isset($row['Submitted'])) $csvData .= '"'.$row['Submitted'].'"'."\n"; if(isset($row['Submitted'])) $csvData .= '"'.$row['Submitted'].'"'."\n";
else $csvData .= '\n'; else $csvData .= "\n";
} }
} else { } else {
user_error("No submissions to export.", E_USER_ERROR); user_error("No submissions to export.", E_USER_ERROR);
} }
if(class_exists('SS_HTTPRequest')) { if(SapphireTest::is_running_test()) {
SS_HTTPRequest::send_file($csvData, $fileName)->output(); return $csvData;
} else { }
HTTPRequest::send_file($csvData, $fileName)->output(); else {
SS_HTTPRequest::send_file($csvData, $fileName)->output();
} }
} else { } else {
user_error("'$SQL_ID' is a valid type, but we can't find a UserDefinedForm in the database that matches the ID.", E_USER_ERROR); user_error("'$SQL_ID' is a valid type, but we can't find a UserDefinedForm in the database that matches the ID.", E_USER_ERROR);
} }
} else {
user_error("'$SQL_ID' is not a valid UserDefinedForm ID.", E_USER_ERROR);
}
} }
/** /**
@ -163,20 +179,28 @@ class SubmittedFormReportField extends FormField {
* *
* @return Redirect|Boolean * @return Redirect|Boolean
*/ */
public function deletesubmissions() { public function deletesubmissions($id = false) {
$SQL_ID = (isset($_REQUEST['id'])) ? Convert::raw2sql($_REQUEST['id']) : false; if($id && is_int($id)) {
if($SQL_ID) { $SQL_ID = $id;
}
else {
if(isset($_REQUEST['id'])) {
$SQL_ID = Convert::raw2sql($_REQUEST['id']);
}
}
if(isset($SQL_ID)) {
$udf = DataObject::get_by_id("UserDefinedForm", $SQL_ID); $udf = DataObject::get_by_id("UserDefinedForm", $SQL_ID);
$submissions = $udf->Submissions(); $submissions = $udf->Submissions();
if($submissions) { if($submissions) {
foreach($submissions as $submission) { foreach($submissions as $submission) {
// delete the submission @see $submission->onBeforeDelete() for more info
$submission->delete(); $submission->delete();
} }
return (Director::is_ajax()) ? true : Director::redirectBack(); return (Director::is_ajax() || SapphireTest::is_running_test()) ? true : Director::redirectBack();
} }
} }
return (Director::is_ajax()) ? false : Director::redirectBack(); return (Director::is_ajax() || SapphireTest::is_running_test()) ? false : Director::redirectBack();
} }
/** /**
@ -184,16 +208,24 @@ class SubmittedFormReportField extends FormField {
* *
* @return Redirect|Boolean * @return Redirect|Boolean
*/ */
public function deletesubmission() { public function deletesubmission($id = false) {
$SQL_ID = (isset($_REQUEST['id'])) ? Convert::raw2sql($_REQUEST['id']) : false; if($id && is_int($id)) {
if($SQL_ID) { $SQL_ID = $id;
}
else {
if(isset($_REQUEST['id'])) {
$SQL_ID = Convert::raw2sql($_REQUEST['id']);
}
}
if(isset($SQL_ID)) {
$submission = DataObject::get_by_id("SubmittedForm", $SQL_ID); $submission = DataObject::get_by_id("SubmittedForm", $SQL_ID);
if($submission) { if($submission) {
$submission->delete(); $submission->delete();
return (Director::is_ajax()) ? true : Director::redirectBack(); return (Director::is_ajax() || SapphireTest::is_running_test()) ? true : Director::redirectBack();
} }
} }
return (Director::is_ajax()) ? false : Director::redirectBack(); return (Director::is_ajax() || SapphireTest::is_running_test()) ? false : Director::redirectBack();
} }
} }

View File

@ -69,10 +69,11 @@
* we let the href of the delete link to do all the work for us * we let the href of the delete link to do all the work for us
*/ */
$("#FormSubmissions .deleteSubmission").click(function() { $("#userforms-submissions .deleteSubmission").click(function() {
var deletedSubmission = $(this); var deletedSubmission = $(this);
$.post($(this).attr('href'), function(data) { $.post($(this).attr('href'), function(data) {
deletedSubmission.parents('div.report').fadeOut(); deletedSubmission.parents('div.userform-submission').fadeOut();
}); });
return false; return false;
}); });

View File

@ -1,18 +1,17 @@
<div class="reports" id="FormSubmissions"> <div id="userforms-submissions">
<% if Submissions %> <% if Submissions %>
<ul class="userforms-submission-actions">
<ul class="formSubmissionActions">
<!-- @todo work out why url_handlers dont like /export/2 -->
<li><a href="{$Top.Link}/export/?id={$RecordID}"><% _t('EXPORTSUBMISSIONS', 'Export submissions to CSV') %></a></li> <li><a href="{$Top.Link}/export/?id={$RecordID}"><% _t('EXPORTSUBMISSIONS', 'Export submissions to CSV') %></a></li>
<li><a href="{$Top.Link}/deletesubmissions/?id={$RecordID}" class="deleteSubmission"><% _t('DELETEALLSUBMISSIONS', 'Delete All Submissions') %></a></li> <li><a href="{$Top.Link}/deletesubmissions/?id={$RecordID}" class="deleteSubmission"><% _t('DELETEALLSUBMISSIONS', 'Delete All Submissions') %></a></li>
</ul> </ul>
<% control Submissions %> <% control Submissions %>
<div class="report"> <div class="userform-submission">
<h4 class="submitted"><% _t('SUBMITTED', 'Submitted at') %> $Created.Nice. <a href="{$Top.Link}/deletesubmission/?id={$ID}" class="deleteSubmission"><% _t('DELETESUBMISSION', 'Delete Submission') %></a></h4> <h4><% _t('SUBMITTED', 'Submitted at') %> $Created.Nice. <a href="{$Top.Link}/deletesubmission/?id={$ID}" class="deleteSubmission"><% _t('DELETESUBMISSION', 'Delete Submission') %></a></h4>
<table> <table>
<% control FieldValues %> <% control Values %>
<tr> <tr>
<td class="field">$Title</td> <td class="field">$Title</td>
<td class="value">$FormattedValue</td> <td class="value">$FormattedValue</td>
@ -21,8 +20,10 @@
</table> </table>
</div> </div>
<% end_control %> <% end_control %>
<% if Submissions.MoreThanOnePage %> <% if Submissions.MoreThanOnePage %>
<div class="pagination"> <div class="userforms-submissions-pagination">
<% if Submissions.NotFirstPage %> <% if Submissions.NotFirstPage %>
<a class="prev" href="javascript:void(0)" onclick="jQuery('.middleColumn').parent().load(jQuery('base').get(0).href+'/{$Top.Link}/getSubmissions/?start={$Submissions.PrevStart}');" title="View the previous page">Previous page</a> <a class="prev" href="javascript:void(0)" onclick="jQuery('.middleColumn').parent().load(jQuery('base').get(0).href+'/{$Top.Link}/getSubmissions/?start={$Submissions.PrevStart}');" title="View the previous page">Previous page</a>
<% end_if %> <% end_if %>
@ -35,5 +36,6 @@
</div> </div>
<% end_if %> <% end_if %>
<% end_if %> <% end_if %>
<p class="noSubmissions" <% if Submissions %>style="display: none"<% end_if %>><% _t('NOSUBMISSIONS', 'No Submissions') %></p>
<p class="userforms-nosubmissions" <% if Submissions %>style="display: none"<% end_if %>><% _t('NOSUBMISSIONS', 'No Submissions') %></p>
</div> </div>

View File

@ -194,12 +194,6 @@ class EditableFormFieldTest extends FunctionalTest {
function testEditableDropdownField() { function testEditableDropdownField() {
$dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown'); $dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown');
$option1 = $this->objFromFixture('EditableOption', 'option-1');
$option2 = $this->objFromFixture('EditableOption', 'option-2');
$dropdown->Options()->add($option1);
$dropdown->Options()->add($option2);
$field = $dropdown->getFormField(); $field = $dropdown->getFormField();
@ -212,18 +206,12 @@ class EditableFormFieldTest extends FunctionalTest {
function testEditableRadioField() { function testEditableRadioField() {
$radio = $this->objFromFixture('EditableRadioField', 'radio-field'); $radio = $this->objFromFixture('EditableRadioField', 'radio-field');
$option1 = $this->objFromFixture('EditableOption', 'option-1');
$option2 = $this->objFromFixture('EditableOption', 'option-2');
$radio->Options()->add($option1);
$radio->Options()->add($option2);
$field = $radio->getFormField(); $field = $radio->getFormField();
$this->assertThat($field, $this->isInstanceOf('OptionsetField')); $this->assertThat($field, $this->isInstanceOf('OptionsetField'));
$values = $field->getSource(); $values = $field->getSource();
$this->assertEquals(array('Option 1' => 'Option 1', 'Option 2' => 'Option 2'), $values); $this->assertEquals(array('Option 5' => 'Option 5', 'Option 6' => 'Option 6'), $values);
} }
function testTitleField() { function testTitleField() {
@ -255,4 +243,59 @@ class EditableFormFieldTest extends FunctionalTest {
$this->assertEquals($text->getSettingFieldName('Foo'), "Fields[". $text->ID ."][CustomSettings][Foo]"); $this->assertEquals($text->getSettingFieldName('Foo'), "Fields[". $text->ID ."][CustomSettings][Foo]");
} }
function testMultipleOptionDuplication() {
$dropdown = $this->objFromFixture('EditableDropdown','basic-dropdown');
$clone = $dropdown->duplicate();
$this->assertEquals($clone->Options()->Count(), $dropdown->Options()->Count());
foreach($clone->Options() as $option) {
$orginal = $dropdown->Options()->find('Title', $option->Title);
$this->assertEquals($orginal->Sort, $option->Sort);
}
}
function testMultipleOptionPopulateFromPostData() {
$dropdown = $this->objFromFixture('EditableDropdown','basic-dropdown');
$data = array();
foreach($dropdown->Options() as $option) {
$orginal[$option->ID] = array(
'Title' => $option->Title,
'Sort' => $option->Sort
);
$data[$option->ID] = array(
'Title' => 'New - '. $option->Title,
'Sort' => $option->Sort + 1
);
}
$dropdown->populateFromPostData($data);
$count = $dropdown->Options()->Count();
foreach($dropdown->Options() as $option) {
$this->assertEquals($option->Title, 'New - '. $orginal[$option->ID]['Title']);
$this->assertEquals($option->Sort, $orginal[$option->ID]['Sort'] + 1);
}
unset($data[1]);
$dropdown->populateFromPostData($data);
$this->assertEquals($dropdown->Options()->Count(), $count-1);
}
function testEditableTextFieldConfiguration() {
$text = $this->objFromFixture('EditableTextField', 'basic-text');
$configuration = $text->getFieldConfiguration();
Debug::show($configuration);
}
} }

View File

@ -28,7 +28,7 @@ class FieldEditorTest extends FunctionalTest {
function testSaveInto() { function testSaveInto() {
$this->logInWithPermission('ADMIN'); $this->logInWithPermission('ADMIN');
// @todo
} }
function testAddField() { function testAddField() {

View File

@ -4,27 +4,105 @@ class SubmittedFormTest extends FunctionalTest {
static $fixture_file = 'userforms/tests/SubmittedFormTest.yml'; static $fixture_file = 'userforms/tests/SubmittedFormTest.yml';
function testReportSubmissions() { protected $controller, $form, $page, $field;
function setUp() {
parent::setUp();
$this->page = $this->objFromFixture('UserDefinedForm', 'popular-form');
$this->controller = new SubmittedFormTest_Controller($this->page);
$this->form = $this->controller->Form();
$this->field = $this->form->dataFieldByName('Report');
}
function testSubmissions() {
$submissions = $this->field->Submissions();
// test with 11 submissions. Should be over 2 pages. 10 per page.
// @todo add tests to ensure the order
$this->assertEquals($submissions->Count(), 10);
$this->assertEquals($submissions->TotalPages(), 2);
$this->assertEquals($submissions->TotalItems(), 11);
}
function testGetSubmissionns() {
$template = $this->field->getSubmissions();
$parser = new CSSContentParser($template);
// check to ensure that the pagination exists
$pagination = $parser->getBySelector('.userforms-submissions-pagination');
$this->assertEquals(str_replace("\n", ' ',(string) $pagination[0]->span), "Viewing rows 0 - 10 of 11 rows");
$this->assertEquals(str_replace("\n", ' ',(string) $pagination[0]->a), "Next page");
// ensure the actions exist
$actions = $parser->getBySelector('.userforms-submission-actions');
$this->assertEquals(count($actions[0]->li), 2);
// submissions
$submissions = $parser->getBySelector('.userform-submission');
$this->assertEquals(count($submissions), 10);
} }
function testCSVExport() { function testCSVExport() {
$export = $this->field->export($this->page->ID);
// export it back to an array (rather than string)
$exportLines = explode("\n", $export);
$data = array();
array_pop($exportLines);
foreach($exportLines as $line) {
$line = explode("\",\"", $line);
$clean = array();
foreach($line as $part) {
$clean[] = trim($part, "\"");
}
$data[] = $clean;
}
// check the headers are fine
$this->assertEquals($data[0], array(
'Submitted Title','Submitted Title 2','Submitted'
));
// check the number of records in the export
$this->assertEquals(count($data), 12);
$this->assertEquals($data[1][0], 'Value 1');
$this->assertEquals($data[1][1], "");
$this->assertEquals($data[2][0], "");
$this->assertEquals($data[2][1], 'Value 2');
} }
function testdeletesubmission() { function testdeletesubmission() {
$submission = $this->objFromFixture('SubmittedForm', 'long-1');
$count = $this->page->Submissions()->Count();
$this->assertTrue($this->field->deletesubmission($submission->ID));
$this->assertEquals($count - 1, $this->page->Submissions()->Count());
$this->assertFalse($this->field->deletesubmission(-1));
} }
function testdeletesubmissions() { function testdeletesubmissions() {
$this->assertTrue($this->field->deletesubmissions($this->page->ID));
$this->assertEquals($this->page->Submissions()->Count(), 0);
} }
function testOnBeforeDeleteOfForm() { function testOnBeforeDeleteOfForm() {
$field = $this->objFromFixture('SubmittedFormField', 'submitted-form-field-1'); $field = $this->objFromFixture('SubmittedFormField', 'submitted-form-field-1');
$form = $field->Parent(); $form = $field->Parent();
$this->assertEquals($form->FieldValues()->Count(), 2); $this->assertEquals($form->Values()->Count(), 2);
$form->delete(); $form->delete();
$fields = DataObject::get('SubmittedFormField', "ParentID = '$form->ID'"); $fields = DataObject::get('SubmittedFormField', "ParentID = '$form->ID'");
@ -60,9 +138,17 @@ class SubmittedFormTest extends FunctionalTest {
} }
class SubmittedFormTest_Controller extends Controller { class SubmittedFormTest_Controller extends ContentController {
function ReportField() { function Form() {
return new Form($this, 'ReportField', new FieldSet(new SubmittedFormReportField('Report'), new FieldSet())); $form = new Form($this, 'Form', new FieldSet(new SubmittedFormReportField('Report')), new FieldSet(new FormAction('Submit')));
$form->loadDataFrom($this->data());
return $form;
}
function forTemplate() {
return $this->renderWith(array('ContentController'));
} }
} }

View File

@ -1,22 +1,49 @@
SubmittedForm:
submitted-form-1:
submitted-form-2:
long-1:
long-2:
long-3:
long-4:
long-5:
long-6:
long-7:
long-8:
long-9:
long-10:
long-11:
UserDefinedForm: UserDefinedForm:
form-page: form-page:
Title: Form Title: Form
Submissions: =>SubmittedForm.submitted-form-1
form-page-2: form-page-2:
Title: Second Form Title: Second Form
Submissions: =>SubmittedForm.submitted-form-2
popular-form:
Title: Popular Form
Submissions: =>SubmittedForm.long-1, =>SubmittedForm.long-2, =>SubmittedForm.long-3, =>SubmittedForm.long-4, =>SubmittedForm.long-5, =>SubmittedForm.long-6, =>SubmittedForm.long-7, =>SubmittedForm.long-8, =>SubmittedForm.long-9, =>SubmittedForm.long-10, =>SubmittedForm.long-11
File: File:
uploaded-file: uploaded-file:
Name: My File Name: My File
Filename: my-file.jpg Filename: my-file.jpg
SubmittedForm:
submitted-form-1:
Parent: =>UserDefinedForm.form-page
submitted-form-2:
Parent: =>UserDefinedForm.form-page-2
SubmittedFormField: SubmittedFormField:
submitted-form-field-1: submitted-form-field-1:
Parent: =>SubmittedForm.submitted-form-1 Parent: =>SubmittedForm.submitted-form-1
@ -33,6 +60,18 @@ SubmittedFormField:
Testing until I cannot Testing until I cannot
I love my testing I love my testing
long-submitted-1:
Name: Submitted Name
Title: Submitted Title
Parent: =>SubmittedForm.long-1
Value: Value 1
long-submitted-2:
Parent: =>SubmittedForm.long-2
Name: Submitted Name 2
Title: Submitted Title 2
Value: Value 2
SubmittedFileField: SubmittedFileField:
submitted-file-1: submitted-file-1:
Name: File Field Name: File Field

View File

@ -2,12 +2,11 @@ EditableOption:
option-1: option-1:
Name: Option1 Name: Option1
Title: Option 1 Title: Option 1
Sort: 1
option-2: option-2:
Name: Option2 Name: Option2
Title: Option 2 Title: Option 2
Sort: 2
department-1: department-1:
Name: dept1 Name: dept1
Title: sales@example.com Title: sales@example.com
@ -16,6 +15,22 @@ EditableOption:
Name: dept2 Name: dept2
Title: accounts@example.com Title: accounts@example.com
option-3:
Name: Option3
Title: Option 3
option-4:
Name: Option4
Title: Option 4
option-5:
Name: Option5
Title: Option 5
option-6:
Name: Option6
Title: Option 6
UserDefinedForm_EmailRecipient: UserDefinedForm_EmailRecipient:
recipient-1: recipient-1:
EmailAddress: test@example.com EmailAddress: test@example.com
@ -73,7 +88,7 @@ EditableCheckboxGroupField:
checkbox-group: checkbox-group:
Name: check-box-group Name: check-box-group
Title: Check box group Title: Check box group
Options: =>EditableOption.option-1, =>EditableOption.option-2 Options: =>EditableOption.option-3, =>EditableOption.option-4
EditableEmailField: EditableEmailField:
email-field: email-field:
@ -85,7 +100,7 @@ EditableRadioField:
radio-field: radio-field:
Name: radio-option Name: radio-option
Title: Radio Option Title: Radio Option
Options: =>EditableOption.option-1, =>EditableOption.option-2 Options: =>EditableOption.option-5, =>EditableOption.option-6
UserDefinedForm: UserDefinedForm: