Implemented folder and file moving.
This commit is contained in:
parent
f7d08f1197
commit
86b9f58465
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.'
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"] {
|
||||
|
|
|
|||
|
|
@ -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') ?>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
<?= Form::open() ?>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="popup">×</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>
|
||||
Loading…
Reference in New Issue