mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
ENHANCEMENT Changed AssetAdmin interface 'delete' action to behave same as main CMS interface: Show 'batch actions' with dropdown. Added AssetAdmin_DeleteBatchAction class.
ENHANCEMENT Moved 'Sync files' action in AssetAdmin from toplevel tab to the bottom of the tree and hooked up to AssetAdmin->SyncForm to avoid hardcoding the URL. ENHANCEMENT Changed AssetAdmin interface 'create' button to show dialog and 'go' button, and behave similar to the main CMS interface git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92802 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
e47ce88853
commit
067b7bcaeb
@ -36,8 +36,8 @@ class AssetAdmin extends LeftAndMain {
|
|||||||
public static $apply_restrictions_to_admin = false;
|
public static $apply_restrictions_to_admin = false;
|
||||||
|
|
||||||
static $allowed_actions = array(
|
static $allowed_actions = array(
|
||||||
'addfolder',
|
'doAdd',
|
||||||
'deletefolder',
|
'AddForm',
|
||||||
'deletemarked',
|
'deletemarked',
|
||||||
'DeleteItemsForm',
|
'DeleteItemsForm',
|
||||||
'deleteUnusedThumbnails',
|
'deleteUnusedThumbnails',
|
||||||
@ -50,7 +50,9 @@ class AssetAdmin extends LeftAndMain {
|
|||||||
'savefile',
|
'savefile',
|
||||||
'uploadiframe',
|
'uploadiframe',
|
||||||
'UploadForm',
|
'UploadForm',
|
||||||
'deleteUnusedThumbnails' => 'ADMIN'
|
'deleteUnusedThumbnails' => 'ADMIN',
|
||||||
|
'batchactions',
|
||||||
|
'BatchActionsForm'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,6 +107,8 @@ class AssetAdmin extends LeftAndMain {
|
|||||||
};
|
};
|
||||||
JS
|
JS
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CMSBatchActionHandler::register('delete', 'AssetAdmin_DeleteBatchAction', 'Folder');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -506,10 +510,33 @@ JS;
|
|||||||
|
|
||||||
// Data saving handlers
|
// Data saving handlers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Form
|
||||||
|
*/
|
||||||
|
function AddForm() {
|
||||||
|
$typeMap = array('Folder' => singleton('Folder')->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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new folder and return its details suitable for ajax.
|
* Add a new folder and return its details suitable for ajax.
|
||||||
*/
|
*/
|
||||||
public function addfolder() {
|
public function doAdd() {
|
||||||
$parent = ($_REQUEST['ParentID'] && is_numeric($_REQUEST['ParentID'])) ? (int)$_REQUEST['ParentID'] : 0;
|
$parent = ($_REQUEST['ParentID'] && is_numeric($_REQUEST['ParentID'])) ? (int)$_REQUEST['ParentID'] : 0;
|
||||||
$name = (isset($_REQUEST['Name'])) ? basename($_REQUEST['Name']) : _t('AssetAdmin.NEWFOLDER',"NewFolder");
|
$name = (isset($_REQUEST['Name'])) ? basename($_REQUEST['Name']) : _t('AssetAdmin.NEWFOLDER',"NewFolder");
|
||||||
|
|
||||||
@ -552,61 +579,49 @@ JS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Form
|
* Batch Actions Handler
|
||||||
*/
|
*/
|
||||||
function DeleteItemsForm() {
|
function batchactions() {
|
||||||
$form = new Form(
|
return new CMSBatchActionHandler($this, 'batchactions', 'Folder');
|
||||||
$this,
|
|
||||||
'DeleteItemsForm',
|
|
||||||
new FieldSet(
|
|
||||||
new LiteralField('SelectedPagesNote',
|
|
||||||
sprintf('<p>%s</p>', _t('AssetAdmin_left.ss.SELECTTODEL','Select the folders that you want to delete and then click the button below'))
|
|
||||||
),
|
|
||||||
new HiddenField('csvIDs')
|
|
||||||
),
|
|
||||||
new FieldSet(
|
|
||||||
new FormAction('deletefolder', _t('AssetAdmin_left.ss.DELFOLDERS','Delete the selected folders'))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$form->addExtraClass('actionparams');
|
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a folder
|
* @return Form
|
||||||
*/
|
*/
|
||||||
public function deletefolder() {
|
function BatchActionsForm() {
|
||||||
$script = '';
|
$actions = $this->batchactions()->batchActionList();
|
||||||
$ids = split(' *, *', $_REQUEST['csvIDs']);
|
$actionsMap = array();
|
||||||
$script = '';
|
foreach($actions as $action) $actionsMap[$action->Link] = $action->Title;
|
||||||
|
|
||||||
if(!$ids) return false;
|
$form = new Form(
|
||||||
|
$this,
|
||||||
|
'BatchActionsForm',
|
||||||
|
new FieldSet(
|
||||||
|
new LiteralField(
|
||||||
|
'Intro',
|
||||||
|
sprintf('<p><small>%s</small></p>',
|
||||||
|
_t(
|
||||||
|
'CMSMain_left.ss.SELECTPAGESACTIONS',
|
||||||
|
'Select the pages that you want to change & then click an action:'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new HiddenField('csvIDs'),
|
||||||
|
new DropdownField(
|
||||||
|
'Action',
|
||||||
|
false,
|
||||||
|
$actionsMap
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new FieldSet(
|
||||||
|
// TODO i18n
|
||||||
|
new FormAction('submit', "Go")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$form->addExtraClass('actionparams');
|
||||||
|
$form->unsetValidator();
|
||||||
|
|
||||||
foreach($ids as $id) {
|
return $form;
|
||||||
if(is_numeric($id)) {
|
|
||||||
$record = DataObject::get_by_id($this->stat('tree_class'), $id);
|
|
||||||
if($record) {
|
|
||||||
$record->delete();
|
|
||||||
$record->destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$size = sizeof($ids);
|
|
||||||
if($size > 1) {
|
|
||||||
$message = $size.' '._t('AssetAdmin.FOLDERSDELETED', 'folders deleted.');
|
|
||||||
} else {
|
|
||||||
$message = $size.' '._t('AssetAdmin.FOLDERDELETED', 'folder deleted.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($brokenPageList)) {
|
|
||||||
$message .= ' '._t('AssetAdmin.NOWBROKEN', 'The following pages now have broken links:').'<ul>'.addslashes($brokenPageList).'</ul>'.
|
|
||||||
_t('AssetAdmin.NOWBROKEN2', 'Their owners have been emailed and they will fix up those pages.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$script .= "statusMessage('$message');";
|
|
||||||
echo $script;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removefile(){
|
public function removefile(){
|
||||||
@ -754,4 +769,38 @@ JS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Delete multiple {@link Folder} records (and the associated filesystem nodes).
|
||||||
|
* Usually used through the {@link AssetAdmin} interface.
|
||||||
|
*
|
||||||
|
* @package cms
|
||||||
|
* @subpackage batchactions
|
||||||
|
*/
|
||||||
|
class AssetAdmin_DeleteBatchAction extends CMSBatchAction {
|
||||||
|
function getActionTitle() {
|
||||||
|
// _t('AssetAdmin_left.ss.SELECTTODEL','Select the folders that you want to delete and then click the button below')
|
||||||
|
return _t('AssetAdmin_DeleteBatchAction.TITLE', 'Delete folders');
|
||||||
|
}
|
||||||
|
|
||||||
|
function run(DataObjectSet $records) {
|
||||||
|
$status = array(
|
||||||
|
'modified'=>array(),
|
||||||
|
'deleted'=>array()
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($records as $record) {
|
||||||
|
$id = $record->ID;
|
||||||
|
|
||||||
|
// Perform the action
|
||||||
|
if($record->canDelete()) $record->delete();
|
||||||
|
|
||||||
|
$status['deleted'][$id] = array();
|
||||||
|
|
||||||
|
$record->destroy();
|
||||||
|
unset($record);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Convert::raw2json($status);
|
||||||
|
}
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -22,3 +22,20 @@
|
|||||||
.DraggedHandle {
|
.DraggedHandle {
|
||||||
width: 30em !important;
|
width: 30em !important;
|
||||||
}
|
}
|
||||||
|
form#Form_AddForm fieldset {
|
||||||
|
float: left;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
form#Form_AddForm .field span.readonly {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#TreeActions-sync {
|
||||||
|
/* Same as .checkboxAboveTree */
|
||||||
|
border-top: 1px solid #CCCCCC;
|
||||||
|
padding: .5em;
|
||||||
|
}
|
@ -10,132 +10,146 @@ SiteTreeHandlers.showRecord_url = 'admin/assets/show/';
|
|||||||
SiteTreeHandlers.controller_url = 'admin/assets';
|
SiteTreeHandlers.controller_url = 'admin/assets';
|
||||||
|
|
||||||
var _HANDLER_FORMS = {
|
var _HANDLER_FORMS = {
|
||||||
addpage : 'Form_AddPageOptionsForm',
|
addpage : 'Form_AddForm',
|
||||||
deletepage : 'Form_DeleteItemsForm',
|
deletepage : 'Form_DeleteItemsForm',
|
||||||
sortitems : 'sortitems_options'
|
sortitems : 'sortitems_options'
|
||||||
};
|
};
|
||||||
|
|
||||||
(function($) {
|
(function($) {
|
||||||
/**
|
/**
|
||||||
* Overload the "Create" tab to execute action instead of
|
* @class Simple form with a page type dropdown
|
||||||
* opening the tab content.
|
* which creates a new page through #Form_EditForm and adds a new tree node.
|
||||||
|
* @name ss.Form_AddForm
|
||||||
|
* @requires ss.i18n
|
||||||
|
* @requires ss.Form_EditForm
|
||||||
*/
|
*/
|
||||||
$('#TreeActions-create-btn').concrete('ss', function($) {
|
$('#Form_AddForm').concrete(function($) {
|
||||||
return {
|
return/** @lends ss.Form_AddForm */{
|
||||||
onmatch: function() {
|
/**
|
||||||
this.bind('click', function(e) {
|
* @type DOMElement
|
||||||
var form = $('form#addpage_options');
|
*/
|
||||||
jQuery.post(
|
Tree: null,
|
||||||
form.attr('action'),
|
|
||||||
form.serialize(),
|
|
||||||
function(data) {
|
|
||||||
|
|
||||||
}
|
/**
|
||||||
);
|
* @type Array Internal counter to create unique page identifiers prior to ajax saving
|
||||||
return false;
|
*/
|
||||||
})
|
_NewPages: [],
|
||||||
|
|
||||||
|
onmatch: function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.bind('submit', function(e) {
|
||||||
|
return self._submit(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
Observable.applyTo(this[0]);
|
||||||
|
|
||||||
|
var tree = jQuery('#sitetree')[0];
|
||||||
|
this.setTree(tree);
|
||||||
|
},
|
||||||
|
|
||||||
|
_submit: function(e) {
|
||||||
|
var newPages = this._NewPages();
|
||||||
|
var tree = this.Tree();
|
||||||
|
var parentID = (tree.firstSelected()) ? tree.getIdxOf(tree.firstSelected()) : 0;
|
||||||
|
|
||||||
|
// TODO: Remove 'new-' code http://open.silverstripe.com/ticket/875
|
||||||
|
if(parentID && parentID.substr(0,3) == 'new') {
|
||||||
|
alert(ss.i18n._t('CMSMAIN.WARNINGSAVEPAGESBEFOREADDING'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tree.firstSelected() && jQuery(tree.firstSelected()).hasClass("nochildren")) {
|
||||||
|
alert(ss.i18n._t('CMSMAIN.CANTADDCHILDREN') );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally initalize the new pages tracker
|
||||||
|
if(!newPages[parentID] ) newPages[parentID] = 1;
|
||||||
|
|
||||||
|
// default to first button
|
||||||
|
var button = jQuery(this).find(':submit:first');
|
||||||
|
button.addClass('loading');
|
||||||
|
|
||||||
|
// collect data and submit the form
|
||||||
|
var data = jQuery(this).serializeArray();
|
||||||
|
data.push({name:'Suffix',value:newPages[parentID]++});
|
||||||
|
data.push({name:button.attr('name'),value:button.val()});
|
||||||
|
jQuery('#Form_EditForm').concrete('ss').loadForm(
|
||||||
|
jQuery(this).attr('action'),
|
||||||
|
function() {
|
||||||
|
button.removeClass('loading');
|
||||||
|
},
|
||||||
|
{type: 'POST', data: data}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.set_NewPages(newPages);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}(jQuery));
|
|
||||||
|
|
||||||
|
$('#Form_SyncForm').concrete('ss', function($) {
|
||||||
|
return {
|
||||||
|
onmatch: function() {
|
||||||
|
this.bind('submit', this._onsubmit);
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
|
_onsubmit: function(e) {
|
||||||
|
var button = jQuery(this).find(':submit:first');
|
||||||
|
button.addClass('loading');
|
||||||
|
$.get(
|
||||||
|
jQuery(this).attr('action'),
|
||||||
|
function() {
|
||||||
|
button.removeClass('loading');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
return false;
|
||||||
* Add File Action
|
}
|
||||||
*/
|
};
|
||||||
addfolder = Class.create();
|
});
|
||||||
addfolder.applyTo('#addpage');
|
|
||||||
addfolder.prototype = {
|
|
||||||
initialize: function () {
|
|
||||||
Observable.applyTo($(this.id + '_options'));
|
|
||||||
this.getElementsByTagName('button')[0].onclick = returnFalse;
|
|
||||||
$(this.id + '_options').onsubmit = this.form_submit;
|
|
||||||
|
|
||||||
},
|
$('#Form_DeleteItemsForm').concrete('ss', function($) {
|
||||||
|
return {
|
||||||
|
onmatch: function() {
|
||||||
|
$('#TreeActions').bind('tabsselect', function(e, ui) {
|
||||||
|
if($(ui.tab).attr('id') == 'TreeActions-delete-btn') {
|
||||||
|
|
||||||
onclick : function() {
|
}
|
||||||
statusMessage('Creating new folder...');
|
});
|
||||||
this.form_submit();
|
},
|
||||||
/*
|
/**
|
||||||
if(treeactions.toggleSelection(this)) {
|
* @param {Boolean}
|
||||||
var selectedNode = $('sitetree').firstSelected();
|
*/
|
||||||
|
toggleTree: function(bool) {
|
||||||
|
if(bool) {
|
||||||
|
deletefolder.o1 = $('sitetree').observeMethod('SelectionChanged', deletefolder.treeSelectionChanged);
|
||||||
|
deletefolder.o2 = $('Form_DeleteItemsForm').observeMethod('Close', deletefolder.popupClosed);
|
||||||
|
|
||||||
if(selectedNode) {
|
jQuery('#sitetree').addClass('multiselect');
|
||||||
while(selectedNode.parentTreeNode && !selectedNode.hints.defaultChild) {
|
|
||||||
$('sitetree').changeCurrentTo(selectedNode.parentTreeNode);
|
deletefolder.selectedNodes = { };
|
||||||
selectedNode = selectedNode.parentTreeNode;
|
|
||||||
|
var sel = $('sitetree').firstSelected()
|
||||||
|
if(sel) {
|
||||||
|
var selIdx = $('sitetree').getIdxOf(sel);
|
||||||
|
deletefolder.selectedNodes[selIdx] = true;
|
||||||
|
sel.removeNodeClass('current');
|
||||||
|
sel.addNodeClass('selected');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
*/
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
form_submit : function() {
|
};
|
||||||
var st = $('sitetree');
|
});
|
||||||
|
}(jQuery));
|
||||||
$('Form_AddPageOptionsForm').elements.ParentID.value = st.getIdxOf(st.firstSelected());
|
|
||||||
Ajax.SubmitForm('Form_AddPageOptionsForm', null, {
|
|
||||||
onSuccess : this.onSuccess,
|
|
||||||
onFailure : this.showAddPageError
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
onSuccess: function(response) {
|
|
||||||
Ajax.Evaluator(response);
|
|
||||||
// Make it possible to drop files into the new folder
|
|
||||||
DropFileItem.applyTo('#sitetree li');
|
|
||||||
},
|
|
||||||
showAddPageError: function(response) {
|
|
||||||
errorMessage('Error adding folder', response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Look for new files (FilesystemSync) action
|
|
||||||
*/
|
|
||||||
FilesystemSyncClass = Class.create();
|
|
||||||
FilesystemSyncClass.applyTo('#filesystemsync');
|
|
||||||
FilesystemSyncClass.prototype = {
|
|
||||||
initialize: function () {
|
|
||||||
this.getElementsByTagName('button')[0].onclick = returnFalse;
|
|
||||||
},
|
|
||||||
|
|
||||||
onclick : function() {
|
|
||||||
statusMessage('Looking for new files');
|
|
||||||
new Ajax.Request('dev/tasks/FilesystemSyncTask', {
|
|
||||||
onSuccess: function(t) {
|
|
||||||
statusMessage(t.responseText, "good");
|
|
||||||
},
|
|
||||||
onFailure: function(t) {
|
|
||||||
errorMessage("There was an error looking for new files");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete folder action
|
* Delete folder action
|
||||||
*/
|
*/
|
||||||
deletefolder = {
|
deletefolder = {
|
||||||
button_onclick : function() {
|
button_onclick : function() {
|
||||||
if(treeactions.toggleSelection(this)) {
|
|
||||||
deletefolder.o1 = $('sitetree').observeMethod('SelectionChanged', deletefolder.treeSelectionChanged);
|
|
||||||
deletefolder.o2 = $('Form_DeleteItemsForm').observeMethod('Close', deletefolder.popupClosed);
|
|
||||||
|
|
||||||
jQuery('#sitetree').addClass('multiselect');
|
|
||||||
|
|
||||||
deletefolder.selectedNodes = { };
|
|
||||||
|
|
||||||
var sel = $('sitetree').firstSelected()
|
|
||||||
if(sel) {
|
|
||||||
var selIdx = $('sitetree').getIdxOf(sel);
|
|
||||||
deletefolder.selectedNodes[selIdx] = true;
|
|
||||||
sel.removeNodeClass('current');
|
|
||||||
sel.addNodeClass('selected');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,34 +13,18 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#TreeActions-delete" id="TreeActions-delete-btn">
|
<a href="#TreeActions-batchactions" id="batchactions">
|
||||||
<% _t('DELETE','Delete',PR_HIGH) %>
|
<% _t('BATCHACTIONS','Batch Actions',PR_HIGH) %>
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#" title="<% _t('FILESYSTEMSYNC_DESC', 'SilverStripe maintains its own database of the files & images stored in your assets/ folder. Click this button to update that database, if files are added to the assets/ folder from outside SilverStripe, for example, if you have uploaded files via FTP.') %>">
|
|
||||||
<% _t('FILESYSTEMSYNC','Look for new files') %>
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div id="TreeActions-create">
|
<div id="TreeActions-create">
|
||||||
<form class="actionparams" id="addpage_options" action="admin/assets/addfolder">
|
$AddForm
|
||||||
<div>
|
|
||||||
<input type="hidden" name="ParentID" />
|
|
||||||
<input class="action" type="submit" value="<% _t('GO','Go') %>" />
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="TreeActions-delete">
|
<div id="TreeActions-batchactions">
|
||||||
<form class="actionparams" id="deletepage_options" style="display: none" action="admin/assets/deletefolder">
|
$BatchActionsForm
|
||||||
<p><% _t('SELECTTODEL','Select the folders that you want to delete and then click the button below') %></p>
|
|
||||||
<div>
|
|
||||||
<input type="hidden" name="csvIDs" />
|
|
||||||
<input type="submit" value="<% _t('DELFOLDERS','Delete the selected folders') %>" class="action delete" />
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -56,6 +40,10 @@
|
|||||||
$SiteTreeAsUL
|
$SiteTreeAsUL
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="TreeActions-sync">
|
||||||
|
$SyncForm
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
Loading…
Reference in New Issue
Block a user