mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 06:05:56 +00:00
(merged from branches/roa. use "svn log -c <changeset> -g <module-svn-path>" for detailed commit message)
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@60204 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
05ad3c8e1c
commit
83fff5f1c1
@ -42,6 +42,17 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
'delete'
|
||||
);
|
||||
|
||||
/**
|
||||
* Model object currently in manipulation queue. Used for updating Link to point
|
||||
* to the correct generic data object in generated URLs.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $currentModel = false;
|
||||
|
||||
/**
|
||||
* Initialize the model admin interface. Sets up embedded jquery libraries and requisite plugins
|
||||
*/
|
||||
public function init() {
|
||||
parent::init();
|
||||
|
||||
@ -50,13 +61,34 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
user_error('ModelAdmin::init(): Invalid Model class', E_USER_ERROR);
|
||||
}
|
||||
|
||||
Requirements::css('cms/css/ModelAdmin.css');
|
||||
Requirements::css('cms/css/ModelAdmin.css'); // standard layout formatting for management UI
|
||||
Requirements::css('cms/css/silverstripe.tabs.css'); // follows the jQuery UI theme conventions
|
||||
|
||||
Requirements::javascript('jsparty/jquery/jquery.js');
|
||||
Requirements::javascript('jsparty/jquery/livequery/jquery.livequery.js');
|
||||
Requirements::javascript('jsparty/jquery/ui/ui/ui.base.js');
|
||||
Requirements::javascript('jsparty/jquery/ui/ui/ui.tabs.js');
|
||||
Requirements::javascript('jsparty/jquery/ui/plugins/form/jquery.form.js');
|
||||
Requirements::javascript('cms/javascript/ModelAdmin.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add mappings for generic form constructors to automatically delegate to a scaffolded form object.
|
||||
*/
|
||||
function defineMethods() {
|
||||
parent::defineMethods();
|
||||
foreach($this->getManagedModels() as $class) {
|
||||
$this->addWrapperMethod('SearchForm_' . $class, 'getSearchFormForModel');
|
||||
$this->addWrapperMethod('AddForm_' . $class, 'getAddFormForModel');
|
||||
$this->addWrapperMethod('EditForm_' . $class, 'getEditFormForModel');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default link to this controller
|
||||
*
|
||||
* @todo We've specified this in Director::addRules(), why repeat?
|
||||
* @todo extract full URL binding from Director::addRules so that it's not tied to 'admin/crm'
|
||||
* @todo is there a way of removing the dependency on this method from the Form?
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -91,13 +123,11 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo documentation
|
||||
*
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
*/
|
||||
public function save($data, $form) {
|
||||
// @todo implementation
|
||||
Debug::dump($data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +142,7 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
|
||||
$form = new Form(
|
||||
$this,
|
||||
'AddForm_add',
|
||||
"AddForm",
|
||||
new FieldSet(
|
||||
new DropdownField('ClassName', 'Type', $modelMap)
|
||||
),
|
||||
@ -120,6 +150,7 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
new FormAction('add', _t('GenericDataAdmin.CREATE'))
|
||||
)
|
||||
);
|
||||
$form->setFormMethod('get');
|
||||
return $form;
|
||||
}
|
||||
|
||||
@ -156,21 +187,14 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
*/
|
||||
protected function getEditForm($modelClass) {
|
||||
$modelObj = singleton($modelClass);
|
||||
|
||||
$fields = $this->getFieldsForModel($modelObj);
|
||||
|
||||
$formName = "EditForm_$modelClass";
|
||||
$fields = $this->getFieldsForModel($modelObj);
|
||||
$this->getComponentFieldsForModel($modelObj, $fields);
|
||||
$actions = $this->getActionsForModel($modelObj);
|
||||
|
||||
$validator = $this->getValidatorForModel($modelObj);
|
||||
|
||||
$form = new Form(
|
||||
$this,
|
||||
'ModelEditForm',
|
||||
$fields,
|
||||
$actions,
|
||||
$validator
|
||||
);
|
||||
|
||||
// necessary because of overriding the form action - NEED TO VERIFY THIS
|
||||
$fields->push(new HiddenField("executeForm", $formName));
|
||||
$form = new Form($this, $formName, $fields, $actions, $validator);
|
||||
return $form;
|
||||
}
|
||||
|
||||
@ -197,7 +221,28 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
* @return FieldSet
|
||||
*/
|
||||
protected function getFieldsForModel($modelObj) {
|
||||
return $modelObj->getCMSFields();
|
||||
$fields = $modelObj->getCMSFields();
|
||||
if (!$fields->dataFieldByName('ID')) {
|
||||
$fields->push(new HiddenField('ID'));
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update: complex table field generation moved into controller - could be
|
||||
* in the DataObject scaffolding?
|
||||
*
|
||||
* @param unknown_type $modelObj
|
||||
* @return FieldSet of ComplexTableFields
|
||||
*/
|
||||
protected function getComponentFieldsForModel($modelObj, $fieldSet) {
|
||||
foreach($modelObj->has_many() as $relationship => $component) {
|
||||
|
||||
$relationshipFields = array_keys(singleton($component)->searchableFields());
|
||||
$fieldSet->push(new ComplexTableField($this, $relationship, $component, $relationshipFields));
|
||||
|
||||
}
|
||||
return $fieldSet;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,7 +259,6 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
new FormAction('save', _t('GenericDataAdmin.SAVE')),
|
||||
new FormAction('delete', _t('GenericDataAdmin.DELETE'))
|
||||
);
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
@ -230,7 +274,7 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
protected function getValidatorForModel($modelObj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a search form for a single {@link DataObject} subclass.
|
||||
*
|
||||
@ -238,18 +282,19 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
* @return FieldSet
|
||||
*/
|
||||
protected function getSearchFormForModel($modelClass) {
|
||||
if(substr($modelClass,0,11) == 'SearchForm_') $modelClass = substr($modelClass, 11);
|
||||
|
||||
$context = singleton($modelClass)->getDefaultSearchContext();
|
||||
|
||||
$form = new Form(
|
||||
$this,
|
||||
"SearchForm_search_{$modelClass}",
|
||||
"SearchForm_$modelClass",
|
||||
$context->getSearchFields(),
|
||||
new FieldSet(
|
||||
new FormAction('search', _t('MemberTableField.SEARCH'))
|
||||
)
|
||||
);
|
||||
//can't set generic search form as GET because of weirdness with FormObjectLink
|
||||
//$form->setFormMethod('get');
|
||||
$form->setFormMethod('get');
|
||||
return $form;
|
||||
}
|
||||
|
||||
@ -257,25 +302,19 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
* Overwrite the default form action with the path to the DataObject filter
|
||||
* (relies on the search form having the specifically named id as 'SearchForm_DataObject')
|
||||
*
|
||||
* @todo extract hard-coded prefix and generate from Director settings
|
||||
* @todo override default linking to add DataObject based URI paths
|
||||
*/
|
||||
function FormObjectLink($formName) {
|
||||
$segments = explode('_', $formName);
|
||||
if (count($segments) == 3) {
|
||||
return Director::absoluteBaseURL()."admin/crm/{$segments[1]}/{$segments[2]}";
|
||||
} elseif (count($segments) == 2) {
|
||||
return Director::absoluteBaseURL()."admin/crm/{$segments[1]}";
|
||||
} else {
|
||||
return "?executeForm=$formName";
|
||||
}
|
||||
return $this->Link();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to render a data object collection, using the model context to provide filters
|
||||
* and paging.
|
||||
*/
|
||||
function search() {
|
||||
function search($data, $form) {
|
||||
$className = $this->urlParams['ClassName'];
|
||||
Debug::dump($className);
|
||||
if (in_array($className, $this->getManagedModels())) {
|
||||
$model = singleton($className);
|
||||
// @todo need to filter post vars
|
||||
@ -306,7 +345,7 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
* View a generic model using a form object to render a partial HTML
|
||||
* fragment to be embedded via Ajax calls.
|
||||
*/
|
||||
function view() {
|
||||
function show() {
|
||||
$className = $this->urlParams['ClassName'];
|
||||
$ID = $this->urlParams['ID'];
|
||||
|
||||
@ -314,14 +353,15 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
|
||||
$model = DataObject::get_by_id($className, $ID);
|
||||
|
||||
$fields = $model->getCMSFields();
|
||||
/*$fields = $model->getCMSFields();
|
||||
|
||||
$actions = new FieldSet(
|
||||
new FormAction('save', 'Save')
|
||||
);
|
||||
|
||||
$form = new Form($this, $className, $fields, $actions);
|
||||
$form->makeReadonly();
|
||||
$form->makeReadonly();*/
|
||||
$form = $this->getEditForm($className);
|
||||
$form->loadNonBlankDataFrom($model);
|
||||
return $form->forTemplate();
|
||||
}
|
||||
|
31
css/silverstripe.tabs.css
Normal file
31
css/silverstripe.tabs.css
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* SilverStripe specific styles that map to elements from the jQuery UI theme.
|
||||
*
|
||||
* This is not a fully functional tab module, but the file naming convention reflects
|
||||
* the jQuery theme format
|
||||
*
|
||||
* @todo move generic tab styles into this file
|
||||
* @todo add to silverstripe specific branch of /jsparty/jquery/ui/themes
|
||||
*/
|
||||
|
||||
/* Caution! Ensure accessibility in print and other media types... */
|
||||
@media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
|
||||
.ui-tabs-hide {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide useless elements in print layouts... */
|
||||
@media print {
|
||||
.ui-tabs-nav {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stuff for search forms
|
||||
*/
|
||||
.loading {
|
||||
cursor:hourglass;
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
jQuery(document).ready(function() {
|
||||
|
||||
function showRecord(uri) {
|
||||
jQuery.get(uri, function(result){
|
||||
jQuery('#right').html(result);
|
||||
Behaviour.apply();
|
||||
});
|
||||
}
|
||||
|
||||
function saveRecord(uri, data) {
|
||||
//jQuery.post(uri, data, function(result) {)
|
||||
}
|
||||
|
||||
jQuery('#AddForm_holder form').submit(function(){
|
||||
className = jQuery('select option:selected', this).val();
|
||||
// @todo remove dependency on hardcoded URL path
|
||||
requestPath = jQuery(this).attr('action') + '/add/' + className;
|
||||
showRecord(requestPath);
|
||||
return false;
|
||||
});
|
||||
|
||||
// attach generic action handler to all forms displayed in the #right panel
|
||||
jQuery('#right .action').click(function(){
|
||||
alert('do something here');
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery('#SearchForm_holder').tabs();
|
||||
|
||||
jQuery('.tab form').submit(function(){
|
||||
form = jQuery(this);
|
||||
|
||||
var data = {};
|
||||
jQuery('*[name]', form).each(function(){
|
||||
var t = jQuery(this);
|
||||
var val = (t.attr('type') == 'checkbox') ? (t.attr('checked') == true) ? 1 : 0 : t.val();
|
||||
data[t.attr('name')] = val;
|
||||
});
|
||||
|
||||
jQuery.get(form.attr('action'), data, function(result){
|
||||
jQuery('#ResultTable_holder').html(result);
|
||||
jQuery('#ResultTable_holder td').click(function(){
|
||||
td = jQuery(this);
|
||||
showRecord(td.parent().attr('id'));
|
||||
td.parent().parent().find('td').removeClass('active');
|
||||
td.addClass('active').siblings().addClass('active');
|
||||
}).hover(function(){
|
||||
jQuery(this).addClass('over').siblings().addClass('over')
|
||||
}, function(){
|
||||
jQuery(this).removeClass('over').siblings().removeClass('over')
|
||||
});
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user