ENHANCEMENT Adjusted SecurityAdmin to new LeftAndMain API and jquery.concrete javascript. Changed 'delete' and 'create' interface to be more in line with CMSMain parent implementation, and increase code reuse.

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92831 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2009-11-21 03:20:17 +00:00
parent 622d2d46f6
commit e56852dcd8
7 changed files with 135 additions and 237 deletions

View File

@ -99,6 +99,7 @@ class MemberTableField extends ComplexTableField {
function FieldHolder() { function FieldHolder() {
$ret = parent::FieldHolder(); $ret = parent::FieldHolder();
Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/scriptaculous/controls.js");
Requirements::javascript(CMS_DIR . '/javascript/MemberTableField.js'); Requirements::javascript(CMS_DIR . '/javascript/MemberTableField.js');
Requirements::javascript(CMS_DIR . "/javascript/MemberTableField_popup.js"); Requirements::javascript(CMS_DIR . "/javascript/MemberTableField_popup.js");

View File

@ -17,11 +17,11 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
static $subitem_class = 'Member'; static $subitem_class = 'Member';
static $allowed_actions = array( static $allowed_actions = array(
'addgroup',
'addmember', 'addmember',
'autocomplete', 'autocomplete',
'removememberfromgroup', 'removememberfromgroup',
'savemember', 'savemember',
'AddForm',
'AddRecordForm', 'AddRecordForm',
'MemberForm', 'MemberForm',
'EditForm', 'EditForm',
@ -31,55 +31,64 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
public function init() { public function init() {
parent::init(); parent::init();
Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/scriptaculous/controls.js"); Requirements::javascript(CMS_DIR . '/javascript/SecurityAdmin.js');
Requirements::javascript(CMS_DIR . '/javascript/SecurityAdmin.Tree.js');
// needed for MemberTableField (Requirements not determined before Ajax-Call) CMSBatchActionHandler::register('delete', 'SecurityAdmin_DeleteBatchAction', 'Group');
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
Requirements::javascript(SAPPHIRE_DIR . "/javascript/TableListField.js");
Requirements::javascript(SAPPHIRE_DIR . "/javascript/TableField.js");
Requirements::javascript(SAPPHIRE_DIR . "/javascript/ComplexTableField.js");
Requirements::javascript(CMS_DIR . "/javascript/MemberTableField.js");
Requirements::css(THIRDPARTY_DIR . "/greybox/greybox.css");
Requirements::css(SAPPHIRE_DIR . "/css/ComplexTableField.css");
Requirements::javascript(CMS_DIR . '/javascript/SecurityAdmin_left.js');
Requirements::javascript(CMS_DIR . '/javascript/SecurityAdmin_right.js');
Requirements::javascript(THIRDPARTY_DIR . "/greybox/AmiJS.js");
Requirements::javascript(THIRDPARTY_DIR . "/greybox/greybox.js");
} }
public function getEditForm($id = null) { function getEditForm($id = null) {
$record = null; $form = parent::getEditForm($id);
$form->Actions()->insertBefore(
if($id && $id != 'root') {
$record = DataObject::get_by_id($this->stat('tree_class'), $id);
}
if($record && !$record->canView()) return Security::permissionFailure($this);
if($record) {
$fields = $record->getCMSFields();
$actions = new FieldSet(
new FormAction('addmember',_t('SecurityAdmin.ADDMEMBER','Add Member')), new FormAction('addmember',_t('SecurityAdmin.ADDMEMBER','Add Member')),
new FormAction('save',_t('SecurityAdmin.SAVE','Save')) 'action_save'
); );
$form = new Form($this, "EditForm", $fields, $actions); return $form;
$form->loadDataFrom($record); }
if(!$record->canEdit()) { /**
$readonlyFields = $form->Fields()->makeReadonly(); * @return Form
$form->setFields($readonlyFields); */
} function AddForm() {
} else { $class = $this->stat('tree_class');
$form = $this->EmptyForm();
} $typeMap = array('Folder' => singleton($class)->i18n_singular_name());
$typeField = new DropdownField('Type', false, $typeMap, 'Folder');
$form = new Form(
$this,
'AddForm',
new FieldSet(
new HiddenField('ParentID'),
$typeField->performReadonlyTransformation()
),
new FieldSet(
new FormAction('doAdd', _t('AssetAdmin_left.ss.GO','Go'))
)
);
$form->setValidator(null);
$form->addExtraClass('actionparams');
return $form; return $form;
} }
/**
* Add a new group and return its details suitable for ajax.
*/
public function doAdd($data, $form) {
$parentID = (isset($data['ParentID']) && is_numeric($data['ParentID'])) ? (int)$data['ParentID'] : 0;
if(!singleton($this->stat('tree_class'))->canCreate()) return Security::permissionFailure($this);
$record = Object::create($this->stat('tree_class'));
$record->Title = _t('SecurityAdmin.NEWGROUP',"New Group");
$record->ParentID = $parentID;
$record->write();
$form = $this->getEditForm($record->ID);
return $form->formHtmlContent();
}
public function AddRecordForm() { public function AddRecordForm() {
$m = Object::create('MemberTableField', $m = Object::create('MemberTableField',
$this, $this,
@ -269,18 +278,6 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
return $siteTree; return $siteTree;
} }
public function addgroup() {
if(!singleton($this->stat('tree_class'))->canCreate()) return Security::permissionFailure($this);
$newGroup = Object::create($this->stat('tree_class'));
$newGroup->Title = _t('SecurityAdmin.NEWGROUP',"New Group");
$newGroup->Code = "new-group";
$newGroup->ParentID = (is_numeric($_REQUEST['ParentID'])) ? (int)$_REQUEST['ParentID'] : 0;
$newGroup->write();
return $this->returnItemToUser($newGroup);
}
public function EditedMember() { public function EditedMember() {
if(Session::get('currentMember')) return DataObject::get_by_id('Member', (int) Session::get('currentMember')); if(Session::get('currentMember')) return DataObject::get_by_id('Member', (int) Session::get('currentMember'));
} }
@ -315,4 +312,35 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
} }
} }
/**
* Delete multiple {@link Group} records. Usually used through the {@link SecurityAdmin} interface.
*
* @package cms
* @subpackage batchactions
*/
class SecurityAdmin_DeleteBatchAction extends CMSBatchAction {
function getActionTitle() {
return _t('AssetAdmin_DeleteBatchAction.TITLE', 'Delete groups');
}
function run(DataObjectSet $records) {
$status = array(
'modified'=>array(),
'deleted'=>array()
);
foreach($records as $record) {
// TODO Provide better feedback if permission was denied
if(!$record->canDelete()) continue;
$id = $record->ID;
$record->delete();
$status['deleted'][$id] = array();
$record->destroy();
unset($record);
}
return Convert::raw2json($status);
}
}
?> ?>

View File

@ -0,0 +1,10 @@
/**
* Configuration for the left hand tree
*/
if(typeof SiteTreeHandlers == 'undefined') SiteTreeHandlers = {};
SiteTreeHandlers.parentChanged_url = 'admin/security/ajaxupdateparent';
SiteTreeHandlers.orderChanged_url = 'admin/security/ajaxupdatesort';
SiteTreeHandlers.loadPage_url = 'admin/security/getitem';
SiteTreeHandlers.loadTree_url = 'admin/security/getsubtree';
SiteTreeHandlers.showRecord_url = 'admin/security/show/';
SiteTreeHandlers.controller_url = 'admin/security';

View File

@ -1,3 +1,23 @@
(function($) {
/**
* Delete selected folders through "batch actions" tab.
*/
$(document).ready(function() {
$('#Form_BatchActionsForm').concrete('ss').register(
// TODO Hardcoding of base URL
'admin/security/batchactions/delete',
function(ids) {
var confirmed = confirm(
ss.i18n.sprintf(
ss.i18n._t('SecurityAdmin.BATCHACTIONSDELETECONFIRM'),
ids.length
)
);
return (confirmed) ? ids : false;
}
);
});
}(jQuery));
/** /**
* CAUTION: Assumes that a MemberTableField-instance is present as an editing form * CAUTION: Assumes that a MemberTableField-instance is present as an editing form
*/ */

View File

@ -1,159 +0,0 @@
/**
* Configuration for the left hand tree
*/
if(typeof SiteTreeHandlers == 'undefined') SiteTreeHandlers = {};
SiteTreeHandlers.parentChanged_url = 'admin/security/ajaxupdateparent';
SiteTreeHandlers.orderChanged_url = 'admin/security/ajaxupdatesort';
SiteTreeHandlers.loadPage_url = 'admin/security/getitem';
SiteTreeHandlers.loadTree_url = 'admin/security/getsubtree';
SiteTreeHandlers.showRecord_url = 'admin/security/show/';
SiteTreeHandlers.controller_url = 'admin/security';
_HANDLER_FORMS['deletegroup'] = 'deletegroup_options';
/**
* Add page action
* @todo Remove duplication between this and the CMSMain Add page action
*/
var addgroup = {
button_onclick : function() {
addgroup.form_submit();
return false;
},
form_submit : function() {
var st = $('sitetree');
$('addgroup_options').elements.ParentID.value = st.firstSelected() ? st.getIdxOf(st.firstSelected()) : 0;
Ajax.SubmitForm('addgroup_options', null, {
onSuccess : Ajax.Evaluator,
onFailure : function(response) {
errorMessage('Error adding page', response);
}
});
return false;
}
}
/**
* Delete page action
*/
var deletegroup = {
button_onclick : function() {
/*if( $('deletegroup_options').style.display == 'none' )
$('deletegroup_options').style.display = 'block';
else
$('deletegroup_options').style.display = 'none';*/
if(treeactions.toggleSelection(this)) {
$('deletegroup_options').style.display = 'block';
deletegroup.o1 = $('sitetree').observeMethod('SelectionChanged', deletegroup.treeSelectionChanged);
deletegroup.o2 = $('deletegroup_options').observeMethod('Close', deletegroup.popupClosed);
jQuery('#sitetree').addClass('multiselect');
deletegroup.selectedNodes = { };
var sel = $('sitetree').firstSelected();
if(sel && sel.className.indexOf('nodelete') == -1) {
var selIdx = $('sitetree').getIdxOf(sel);
deletegroup.selectedNodes[selIdx] = true;
sel.removeNodeClass('current');
sel.addNodeClass('selected');
}
} else
$('deletegroup_options').style.display = 'none';
return false;
},
treeSelectionChanged : function(selectedNode) {
var idx = $('sitetree').getIdxOf(selectedNode);
if(selectedNode.className.indexOf('nodelete') == -1) {
if(selectedNode.selected) {
selectedNode.removeNodeClass('selected');
selectedNode.selected = false;
deletegroup.selectedNodes[idx] = false;
} else {
selectedNode.addNodeClass('selected');
selectedNode.selected = true;
deletegroup.selectedNodes[idx] = true;
}
}
return false;
},
popupClosed : function() {
jQuery('#sitetree').removeClass('multiselect');
$('sitetree').stopObserving(deletegroup.o1);
$('deletegroup_options').stopObserving(deletegroup.o2);
for(var idx in deletegroup.selectedNodes) {
if(deletegroup.selectedNodes[idx]) {
node = $('sitetree').getTreeNodeByIdx(idx);
if(node) {
node.removeNodeClass('selected');
node.selected = false;
}
}
}
},
form_submit : function() {
var csvIDs = "";
for(var idx in deletegroup.selectedNodes) {
if(deletegroup.selectedNodes[idx]) csvIDs += (csvIDs ? "," : "") + idx;
}
if(csvIDs) {
if(confirm("Do you really want to delete these groups?")) {
$('deletegroup_options').elements.csvIDs.value = csvIDs;
Ajax.SubmitForm('deletegroup_options', null, {
onSuccess : function(response) {
Ajax.Evaluator(response);
var sel;
if((sel = $('sitetree').firstSelected()) && sel.parentNode) sel.addNodeClass('current');
else $('Form_EditForm').innerHTML = "";
treeactions.closeSelection($('deletegroup'));
},
onFailure : function(response) {
errorMessage('Error deleting pages', response);
}
});
$('deletegroup').getElementsByTagName('button')[0].onclick();
}
} else {
alert("Please select at least one group.");
}
return false;
}
}
/**
* Initialisation function to set everything up
*/
Behaviour.addLoader(function () {
// Set up add page
Observable.applyTo($('addgroup_options'));
if($('addgroup')) {
$('addgroup').onclick = addgroup.button_onclick;
$('addgroup').getElementsByTagName('button')[0].onclick = function() {return false;};
$('addgroup_options').onsubmit = addgroup.form_submit;
}
// Set up delete page
Observable.applyTo($('deletegroup_options'));
if($('deletegroup')) {
$('deletegroup').onclick = deletegroup.button_onclick;
$('deletegroup').getElementsByTagName('button')[0].onclick = function() {return false;};
$('deletegroup_options').onsubmit = deletegroup.form_submit;
}
});

View File

@ -30,6 +30,7 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
'CMSMAIN.URLSEGMENTVALIDATION': 'URLs can only be made up of letters, digits and hyphens.', 'CMSMAIN.URLSEGMENTVALIDATION': 'URLs can only be made up of letters, digits and hyphens.',
'AssetAdmin.BATCHACTIONSDELETECONFIRM': "Do you really want to delete %s folders?", 'AssetAdmin.BATCHACTIONSDELETECONFIRM': "Do you really want to delete %s folders?",
'AssetTableField.REALLYDELETE': 'Do you really want to delete the marked files?', 'AssetTableField.REALLYDELETE': 'Do you really want to delete the marked files?',
'AssetTableField.MOVING': 'Moving %s file(s)' 'AssetTableField.MOVING': 'Moving %s file(s)',
'SecurityAdmin.BATCHACTIONSDELETECONFIRM': "Do you really want to delete %s groups?"
}); });
} }

View File

@ -8,40 +8,37 @@
<ul> <ul>
<li> <li>
<a href="#TreeActions-create"> <a href="#TreeActions-create" id="TreeActions-create-btn">
<% _t('CREATE','Create',PR_HIGH) %> <% _t('CREATE','Create',PR_HIGH) %>
</a> </a>
</li> </li>
<li> <li>
<a href="#TreeActions-delete"> <a href="#TreeActions-batchactions" id="batchactions">
<% _t('DELETE','Delete',PR_HIGH) %> <% _t('BATCHACTIONS','Batch Actions',PR_HIGH) %>
</a> </a>
</li> </li>
</ul> </ul>
<div id="TreeActions-create"> <div id="TreeActions-create">
<form class="actionparams" id="addgroup_options" action="admin/security/addgroup"> $AddForm
<input type="hidden" name="ParentID" />
<input class="action" type="submit" value="<% _t('GO','Go') %>" />
</form>
</div> </div>
<div id="TreeActions-delete"> <div id="TreeActions-batchactions">
<form class="actionparams" id="deletegroup_options" style="display: none" action="admin/security/deleteitems"> $BatchActionsForm
<p><% _t('SELECT','Select the pages that you want to delete and then click the button below') %></p>
<input type="hidden" name="csvIDs" />
<input type="submit" value="<% _t('DELGROUPS','Delete the selected groups') %>" class="action delete" />
</form>
</div> </div>
</div> </div>
<div class="checkboxAboveTree"> <div class="checkboxAboveTree">
<input type="checkbox" id="sortitems" /> <label for="sortitems"><% _t('ENABLEDRAGGING','Allow drag &amp; drop reordering', PR_HIGH) %></label> <input type="checkbox" id="sortitems" />
<label for="sortitems">
<% _t('ENABLEDRAGGING','Allow drag &amp; drop reordering', PR_HIGH) %>
</label>
</div> </div>
<div id="sitetree_ul">
$SiteTreeAsUL $SiteTreeAsUL
</div>
</div> </div>