(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@60212 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2008-08-09 05:00:42 +00:00
parent 6401ee7eaf
commit 8a4c5fef72
4 changed files with 112 additions and 6 deletions

View File

@ -40,6 +40,8 @@ abstract class ModelAdmin extends LeftAndMain {
'add',
'edit',
'delete',
'import',
'renderimportform',
'handleList',
'handleItem'
);
@ -59,6 +61,23 @@ abstract class ModelAdmin extends LeftAndMain {
*/
private $currentModel = false;
/**
* List of all {@link DataObject}s which can be imported through
* a subclass of {@link BulkLoader} (mostly CSV data).
* By default {@link CsvBulkLoader} is used, assuming a standard mapping
* of column names to {@link DataObject} properties/relations.
*
* @var array
*/
protected static $model_importers = null;
/**
* Amount of results showing on a single page.
*
* @var int
*/
protected static $page_length = 30;
/**
* Initialize the model admin interface. Sets up embedded jquery libraries and requisite plugins.
*
@ -69,7 +88,7 @@ abstract class ModelAdmin extends LeftAndMain {
// security check for valid models
if(isset($this->urlParams['Action']) && !in_array($this->urlParams['Action'], $this->getManagedModels())) {
user_error('ModelAdmin::init(): Invalid Model class', E_USER_ERROR);
//user_error('ModelAdmin::init(): Invalid Model class', E_USER_ERROR);
}
Requirements::css('cms/css/ModelAdmin.css'); // standard layout formatting for management UI
@ -137,11 +156,56 @@ abstract class ModelAdmin extends LeftAndMain {
return $form;
}
/**
* Generate a CSV import form with an option to select
* one of the "importable" models specified through {@link self::$model_importers}.
*
* @return Form
*/
public function ImportForm() {
$models = $this->getManagedModels();
$modelMap = array();
foreach($this->getModelImporters() as $modelName => $spec) $modelMap[$modelName] = singleton($modelName)->singular_name();
$form = new Form(
$this,
"ImportForm",
new FieldSet(
new DropdownField('ClassName', 'Type', $modelMap),
new FileField('_CsvFile', false)
),
new FieldSet(
new FormAction('import', _t('ModelAdmin.IMPORT', 'Import from CSV'))
)
);
return $form;
}
function add($data, $form, $request) {
$className = $request->requestVar("ClassName");
return $this->$className()->add($request);
}
/**
* Imports the submitted CSV file based on specifications given in
* {@link self::model_importers}.
* Redirects back with a success/failure message.
*
* @todo Figure out ajax submission of files via jQuery.form plugin
*
* @param unknown_type $data
* @param unknown_type $form
* @param unknown_type $request
*/
function import($data, $form, $request) {
$loader = new DemandPointBulkLoader($data['ClassName']);
$results = $loader->load($_FILES['_CsvFile']['tmp_name']);
$resultsCount = ($results) ? $results->Count() : 0;
Session::setFormMessage('Form_ImportForm', "Loaded {$resultsCount} items", 'good');
Director::redirect($_SERVER['HTTP_REFERER'] . '#Form_ImportForm_holder');
}
/**
*
* @uses {@link SearchContext}
@ -175,6 +239,26 @@ abstract class ModelAdmin extends LeftAndMain {
return $models;
}
/**
* Returns all importers defined in {@link self::$model_importers}.
* If none are defined, we fall back to {@link self::managed_models}
* with a default {@link CsvBulkLoader} class. In this case the column names of the first row
* in the CSV file are assumed to have direct mappings to properties on the object.
*
* @return array
*/
protected function getModelImporters() {
$importers = $this->stat('model_importers');
// fallback to all defined models if not explicitly defined
if(!$importers) {
$models = $this->getManagedModels();
foreach($models as $modelName) $importers[$modelName] = 'CsvBulkLoader';
}
return $importers;
}
}
/**
@ -270,7 +354,7 @@ class ModelAdmin_CollectionController extends Controller {
$model = singleton($this->modelClass);
$searchKeys = array_intersect_key($request->getVars(), $model->searchable_fields());
$context = $model->getDefaultSearchContext();
$results = $context->getResults($searchKeys);
$results = $context->getResults($searchKeys, 0, $this->parentController->stat('page_length'));
$output = "";
if ($results) {
$output .= "<table>";

View File

@ -52,4 +52,8 @@ body.ModelAdmin #ResultTable_holder table td.over {
body.ModelAdmin #ResultTable_holder table td.active {
background-color:#555;
color:#fff;
}
body.ModelAdmin #right .tab {
height: 450px; /* @todo add dynamic resizing */
}

View File

@ -56,7 +56,7 @@ jQuery(document).ready(function() {
/**
* Find the selected data object and load its create form
*/
jQuery('#AddForm_holder form').submit(function(){
jQuery('#Form_ManagedModelsSelect').submit(function(){
className = jQuery('select option:selected', this).val();
requestPath = jQuery(this).attr('action').replace('ManagedModelsSelect', className + '/add');
showRecord(requestPath);
@ -83,7 +83,7 @@ jQuery(document).ready(function() {
*
* @todo use livequery to manage ResultTable click handlers
*/
jQuery('.tab form').submit(function(){
jQuery('#SearchForm_holder .tab form').submit(function(){
form = jQuery(this);
data = formData(form);
jQuery.get(form.attr('action'), data, function(result){
@ -103,4 +103,13 @@ jQuery(document).ready(function() {
return false;
});
});
});
/**
* @todo Terrible HACK, but thats the cms UI...
*/
function fixHeight_left() {
fitToParent('LeftPane');
fitToParent('Search_holder',12);
fitToParent('ResultTable_holder',12);
}

View File

@ -1,7 +1,16 @@
<div id="LeftPane">
<h2><% _t('ADDLISTING','Add Listing') %></h2>
<div id="AddForm_holder" class="lefttop">
$ManagedModelsSelect
<ul class="tabstrip">
<li class="first"><a href="#Form_ManagedModelsSelect_holder"><% _t('ADD_TAB_HEADER','Add') %></a></li>
<li class="first"><a href="#Form_ImportForm_holder"><% _t('IMPORT_TAB_HEADER','Import') %></a></li>
</ul>
<div class="tab" id="Form_ManagedModelsSelect_holder">
$ManagedModelsSelect
</div>
<div class="tab" id="Form_ImportForm_holder">
$ImportForm
</div>
</div>
<h2><% _t('SEARCHLISTINGS','Search Listings') %></h2>
<div id="SearchForm_holder" class="leftbottom">