Implemented folder and file moving.

This commit is contained in:
alekseybobkov 2015-03-22 13:07:37 -07:00
parent f7d08f1197
commit 86b9f58465
8 changed files with 240 additions and 8 deletions

View File

@ -208,6 +208,35 @@ class MediaLibrary
return false;
}
/**
* Returns a list of all directories in the Library, optionally excluding some of them.
* @param array $exclude A list of folders to exclude from the result list/
* The folder paths should be specified relative to the Library root.
* @return array
*/
public function listAllDirectories($exclude = [])
{
$fullPath = $this->getMediaPath('/');
$folders = $this->getStorageDisk()->allDirectories($fullPath);
$folders = array_unique($folders, SORT_LOCALE_STRING);
$result = [];
foreach ($folders as $folder) {
$folder = $this->getMediaRelativePath($folder);
if (!strlen($folder))
$folder = '/';
if (Str::startsWith($folder, $exclude))
continue;
$result[] = $folder;
}
return $result;
}
/**
* Returns a file contents.
* @param string $path Specifies the file path relative the the Library root.

View File

@ -260,12 +260,17 @@ return [
'search' => 'Search',
'folder' => 'Folder',
'no_files_found' => 'No files found by your request.',
'delete_empty' => 'Please select files to delete.',
'delete_empty' => 'Please select items to delete.',
'delete_confirm' => 'Do you really want to delete the selected item(s)?',
'error_renaming_file' => 'Error renaming file.',
'error_renaming_file' => 'Error renaming the item.',
'new_folder_title' => 'New folder',
'folder_name' => 'Folder name',
'error_creating_folder' => 'Error creating folder',
'folder_or_file_exist' => 'A folder or file with the specified name already exists.'
'folder_or_file_exist' => 'A folder or file with the specified name already exists.',
'move_empty' => 'Please select items to move.',
'move_popup_title' => 'Move files or folders',
'move_destination' => 'Destination folder',
'please_select_move_dest' => 'Please select a destination folder.',
'move_dest_src_match' => 'Please select another destination folder.'
]
];

View File

@ -286,6 +286,69 @@ class MediaManager extends WidgetBase
];
}
public function onLoadMovePopup()
{
$exclude = Input::get('exclude', []);
if (!is_array($exclude))
throw new SystemException('Invalid input data');
$folders = MediaLibrary::instance()->listAllDirectories($exclude);
$folderList = [];
foreach ($folders as $folder) {
$path = $folder;
if ($folder == '/')
$name = Lang::get('cms::lang.media.library');
else {
$segments = explode('/', $folder);
$name = str_repeat(' ', (count($segments)-1)*4).basename($folder);
}
$folderList[$path] = $name;
}
$this->vars['folders'] = $folderList;
$this->vars['originalPath'] = Input::get('path');
return $this->makePartial('move-form');
}
public function onMoveItems()
{
$dest = trim(Input::get('dest'));
if (!strlen($dest))
throw new ApplicationException(Lang::get('cms::lang.media.please_select_move_dest'));
$dest = MediaLibrary::validatePath($dest);
if ($dest == Input::get('originalPath'))
throw new ApplicationException(Lang::get('cms::lang.media.move_dest_src_match'));
$files = Input::get('files', []);
if (!is_array($files))
throw new SystemException('Invalid input data');
$folders = Input::get('folders', []);
if (!is_array($folders))
throw new SystemException('Invalid input data');
$library = MediaLibrary::instance();
foreach ($files as $path)
$library->moveFile($path, $dest.'/'.basename($path));
foreach ($folders as $path)
$library->moveFolder($path, $dest.'/'.basename($path));
$library->resetCache();
$this->prepareVars();
return [
'#'.$this->getId('item-list') => $this->makePartial('item-list')
];
}
//
// Methods for th internal use
//

View File

@ -331,6 +331,9 @@ div[data-control="media-manager"] table.table tr:hover div.item-title {
div[data-control="media-manager"] table.table tr:hover div.item-title a {
display: block;
}
div[data-control="media-manager"] table.table tr[data-item-type=folder] i.icon-folder {
color: #4da7e8;
}
div[data-control="media-manager"] div[data-control="selection-marker"] {
position: absolute;
z-index: 50;

View File

@ -27,6 +27,9 @@
this.folderPopupShownHandler = this.onFolderPopupShown.bind(this)
this.newFolderSubmitHandler = this.onNewFolderSubmit.bind(this)
this.folderPopupHiddenHandler = this.onFolderPopupHidden.bind(this)
this.movePopupShownHandler = this.onMovePopupShown.bind(this)
this.moveItemsSubmitHandler = this.onMoveItemsSubmit.bind(this)
this.movePopupHiddenHandler = this.onMovePopupHidden.bind(this)
// Instance-bound methods
this.updateSidebarPreviewBound = this.updateSidebarPreview.bind(this)
@ -45,6 +48,7 @@
this.deleteConfirmationBound = this.deleteConfirmation.bind(this)
this.refreshBound = this.refresh.bind(this)
this.folderCreatedBound = this.folderCreated.bind(this)
this.itemsMovedBound = this.itemsMoved.bind(this)
// State properties
this.selectTimer = null
@ -90,6 +94,7 @@
this.deleteConfirmationBound = null
this.refreshBound = null
this.folderCreatedBound = null
this.itemsMovedBound = null
this.sidebarPreviewElement = null
this.itemListElement = null
@ -121,6 +126,8 @@
this.$el.on('mediarefresh', this.refreshBound)
this.$el.on('shown.oc.popup', '[data-command="create-folder"]', this.folderPopupShownHandler)
this.$el.on('hidden.oc.popup', '[data-command="create-folder"]', this.folderPopupHiddenHandler)
this.$el.on('shown.oc.popup', '[data-command="move"]', this.movePopupShownHandler)
this.$el.on('hidden.oc.popup', '[data-command="move"]', this.movePopupHiddenHandler)
if (this.itemListElement)
this.itemListElement.addEventListener('mousedown', this.listMouseDownHandler)
@ -135,6 +142,8 @@
this.$el.off('keyup', '[data-control="search"]', this.searchChangedHandler)
this.$el.off('shown.oc.popup', '[data-command="create-folder"]', this.folderPopupShownHandler)
this.$el.off('hidden.oc.popup', '[data-command="create-folder"]', this.folderPopupHiddenHandler)
this.$el.off('shown.oc.popup', '[data-command="move"]', this.movePopupShownHandler)
this.$el.off('hidden.oc.popup', '[data-command="move"]', this.movePopupHiddenHandler)
if (this.itemListElement) {
this.itemListElement.removeEventListener('mousedown', this.listMouseDownHandler)
@ -153,6 +162,9 @@
this.folderPopupShownHandler = null
this.folderPopupHiddenHandler = null
this.newFolderSubmitHandler = null
this.movePopupShownHandler = null
this.moveItemsSubmitHandler = null
this.movePopupHiddenHandler = null
}
MediaManager.prototype.changeView = function(view) {
@ -710,7 +722,7 @@
// File and folder operations
//
MediaManager.prototype.deleteFiles = function() {
MediaManager.prototype.deleteItems = function() {
var items = this.$el.get(0).querySelectorAll('[data-type="media-item"].selected')
if (!items.length) {
@ -793,6 +805,81 @@
this.afterNavigateBound
}
MediaManager.prototype.moveItems = function(ev) {
var items = this.$el.get(0).querySelectorAll('[data-type="media-item"].selected')
if (!items.length) {
swal({
title: this.options.moveEmpty,
confirmButtonClass: 'btn-default'
})
return
}
var data = {
exclude: [],
path: this.$el.find('[data-type="current-folder"]').val()
}
for (var i = 0, len = items.length; i < len; i++) {
var item = items[i],
path = item.getAttribute('data-path')
if (item.getAttribute('data-item-type') == 'folder')
data.exclude.push(path)
}
$(ev.target).popup({
handler: this.options.alias+'::onLoadMovePopup',
extraData: data
})
}
MediaManager.prototype.onMovePopupShown = function(ev, button, popup) {
$(popup).on('submit.media', 'form', this.moveItemsSubmitHandler)
}
MediaManager.prototype.onMoveItemsSubmit = function(ev) {
var items = this.$el.get(0).querySelectorAll('[data-type="media-item"].selected'),
data = {
dest: $(ev.target).find('select[name=dest]').val(),
originalPath: $(ev.target).find('input[name=originalPath]').val(),
files: [],
folders: []
}
for (var i = 0, len = items.length; i < len; i++) {
var item = items[i],
path = item.getAttribute('data-path')
if (item.getAttribute('data-item-type') == 'folder')
data.folders.push(path)
else
data.files.push(path)
}
$.oc.stripeLoadIndicator.show()
this.$form.request(this.options.alias+'::onMoveItems', {
data: data
}).always(function() {
$.oc.stripeLoadIndicator.hide()
}).done(this.itemsMovedBound)
ev.preventDefault()
return false
}
MediaManager.prototype.onMovePopupHidden = function(ev, button, popup) {
$(popup).off('.media', 'form')
}
MediaManager.prototype.itemsMoved = function() {
this.$el.find('button[data-command="move"]').popup('hide')
this.afterNavigateBound
}
// EVENT HANDLERS
// ============================
@ -834,11 +921,14 @@
this.setFilter($(ev.currentTarget).data('filter'))
break;
case 'delete':
this.deleteFiles()
this.deleteItems()
break;
case 'create-folder':
this.createFolder(ev)
break;
case 'move':
this.moveItems(ev)
break;
}
return false
@ -958,8 +1048,9 @@
MediaManager.DEFAULTS = {
alias: '',
deleteEmpty: 'Please select files to delete',
deleteConfirm: 'Do you really want to delete the selected file(s)?'
deleteEmpty: 'Please select files to delete.',
deleteConfirm: 'Do you really want to delete the selected file(s)?',
moveEmpty: 'Please select files to move.'
}
var old = $.fn.mediaManager

View File

@ -388,6 +388,10 @@ div[data-control="media-manager"] {
display: block;
}
}
tr[data-item-type=folder] i.icon-folder {
color: @color-list-hover-bg;
}
}
div[data-control="selection-marker"] {

View File

@ -3,7 +3,9 @@
class="layout"
data-alias="<?= $this->alias ?>"
data-delete-empty="<?= e(trans('cms::lang.media.delete_empty')) ?>"
data-delete-confirm="<?= e(trans('cms::lang.media.delete_confirm')) ?>">
data-delete-confirm="<?= e(trans('cms::lang.media.delete_confirm')) ?>"
data-move-empty="<?= e(trans('cms::lang.media.move_empty')) ?>"
>
<?= $this->makePartial('toolbar') ?>
<?= $this->makePartial('upload-progress') ?>

View File

@ -0,0 +1,35 @@
<?= Form::open() ?>
<div class="modal-header">
<button type="button" class="close" data-dismiss="popup">&times;</button>
<h4 class="modal-title"><?= e(trans('cms::lang.media.move_popup_title')) ?></h4>
</div>
<div class="modal-body">
<div class="form-group">
<label><?= e(trans('cms::lang.media.move_destination')) ?></label>
<select
class="form-control custom-select"
name="dest"
data-placeholder="<?= e(trans('cms::lang.asset.move_please_select')) ?>">
<option></option>
<?php foreach ($folders as $path=>$folder):?>
<option value="<?= e($path) ?>"><?= e($folder) ?></option>
<?php endforeach ?>
</select>
<input type="hidden" name="originalPath" value="<?= e($originalPath) ?>">
</div>
</div>
<div class="modal-footer">
<button
type="submit"
class="btn btn-primary">
<?= e(trans('cms::lang.asset.move_button')) ?>
</button>
<button
type="button"
class="btn btn-default"
data-dismiss="popup">
<?= e(trans('backend::lang.form.cancel')) ?>
</button>
</div>
</form>