Uses the new file-multi-select-menu component. Towards #7647 Signed-off-by: Abijeet <abijeetpatro@gmail.com>tags/v14.0.0beta1
@@ -169,13 +169,16 @@ table.multiselect th a { | |||
color: #000; | |||
} | |||
table th .columntitle { | |||
display: inline-block; | |||
display: block; | |||
padding: 15px; | |||
height: 50px; | |||
box-sizing: border-box; | |||
-moz-box-sizing: border-box; | |||
vertical-align: middle; | |||
} | |||
table.multiselect th .columntitle { | |||
display: inline-block; | |||
} | |||
table th .columntitle.name { | |||
padding-left: 5px; | |||
margin-left: 50px; | |||
@@ -482,9 +485,7 @@ a.action > img { | |||
line-height: 50px; | |||
padding: 18px 5px; | |||
} | |||
.selectedActions a.delete-selected { | |||
padding-right: 15px; | |||
} | |||
.selectedActions a.hidden { | |||
display: none; | |||
} | |||
@@ -493,10 +494,6 @@ a.action > img { | |||
vertical-align: text-bottom; | |||
margin-bottom: -1px; | |||
} | |||
/* hide the delete icon in name column normal resolutions */ | |||
table th#headerName .selectedActions .delete-selected { | |||
display: none; | |||
} | |||
#fileList td a { | |||
a.action { |
@@ -28,7 +28,7 @@ table td { | |||
table.multiselect thead { | |||
padding-left: 0; | |||
} | |||
#fileList a.action.action-menu img { | |||
padding-left: 0; | |||
} | |||
@@ -41,10 +41,6 @@ table.multiselect thead { | |||
display: none !important; | |||
} | |||
/* show the delete icon in name column in lower resolutions */ | |||
table th#headerName .selectedActions .delete-selected { | |||
display: inline; | |||
} | |||
/* proper notification area for multi line messages */ | |||
#notification-container { | |||
@@ -70,8 +66,14 @@ table.dragshadow { | |||
} | |||
@media only screen and (max-width: 480px) { | |||
table thead { | |||
width: 100% !important; | |||
} | |||
/* Only show icons */ | |||
table th .selectedActions a span:not(.icon) { | |||
table th .selectedActions { | |||
float: right; | |||
} | |||
table th .selectedActions > a span:not(.icon) { | |||
display: none; | |||
} | |||
@@ -88,6 +88,23 @@ | |||
allowLegacyActions: true, | |||
scrollTo: urlParams.scrollto, | |||
filesClient: OC.Files.getClient(), | |||
multiSelectMenu: [ | |||
{ | |||
name: 'moveCopy', | |||
displayName: t('files', 'Move or copy'), | |||
iconClass: 'icon-external', | |||
}, | |||
{ | |||
name: 'download', | |||
displayName: t('files', 'Download'), | |||
iconClass: 'icon-download', | |||
}, | |||
{ | |||
name: 'delete', | |||
displayName: t('files', 'Delete'), | |||
iconClass: 'icon-delete', | |||
} | |||
], | |||
sorting: { | |||
mode: $('#defaultFileSorting').val(), | |||
direction: $('#defaultFileSortingDirection').val() | |||
@@ -130,7 +147,7 @@ | |||
window.FileActions.off('registerAction.app-files', this._onActionsUpdated); | |||
}, | |||
_onActionsUpdated: function(ev, newAction) { | |||
_onActionsUpdated: function(ev) { | |||
// forward new action to the file list | |||
if (ev.action) { | |||
this.fileList.fileActions.registerAction(ev.action); |
@@ -692,21 +692,21 @@ | |||
OCA.Files.FileActions = FileActions; | |||
/** | |||
* Replaces the download icon with a loading spinner and vice versa | |||
* Replaces the button icon with a loading spinner and vice versa | |||
* - also adds the class disabled to the passed in element | |||
* | |||
* @param {jQuery} $downloadButtonElement download fileaction | |||
* @param {jQuery} $buttonElement The button element | |||
* @param {boolean} showIt whether to show the spinner(true) or to hide it(false) | |||
*/ | |||
OCA.Files.FileActions.updateFileActionSpinner = function($downloadButtonElement, showIt) { | |||
var $icon = $downloadButtonElement.find('.icon'); | |||
OCA.Files.FileActions.updateFileActionSpinner = function($buttonElement, showIt) { | |||
var $icon = $buttonElement.find('.icon'); | |||
if (showIt) { | |||
var $loadingIcon = $('<span class="icon icon-loading-small"></span>'); | |||
$icon.after($loadingIcon); | |||
$icon.addClass('hidden'); | |||
} else { | |||
$downloadButtonElement.find('.icon-loading-small').remove(); | |||
$downloadButtonElement.find('.icon').removeClass('hidden'); | |||
$buttonElement.find('.icon-loading-small').remove(); | |||
$buttonElement.find('.icon').removeClass('hidden'); | |||
} | |||
}; | |||
@@ -130,7 +130,7 @@ | |||
* File selection menu, defaults to OCA.Files.FileSelectionMenu | |||
* @type OCA.Files.FileSelectionMenu | |||
*/ | |||
fileSelectionMenu: null, | |||
fileMultiSelectMenu: null, | |||
/** | |||
* Whether selection is allowed, checkboxes and selection overlay will | |||
* be rendered | |||
@@ -293,27 +293,10 @@ | |||
this.fileSummary = this._createSummary(); | |||
this.fileSelectionMenu = new OCA.Files.FileSelectionMenu([ | |||
{ | |||
name: 'moveCopy', | |||
displayName: t('files', 'Move or copy'), | |||
iconClass: 'icon-external', | |||
method: _.bind(this._onClickCopyMoveSelected, this) | |||
}, | |||
{ | |||
name: 'download', | |||
displayName: t('files', 'Download'), | |||
iconClass: 'icon-download', | |||
method: _.bind(this._onClickDownloadSelected, this) | |||
}, | |||
{ | |||
name: 'delete', | |||
displayName: t('files', 'Delete'), | |||
iconClass: 'icon-delete', | |||
method: _.bind(this._onClickDeleteSelected, this) | |||
} | |||
]); | |||
this.$el.find('#selectedActionsList').append(this.fileSelectionMenu.$el); | |||
if (options.multiSelectMenu) { | |||
this.fileMultiSelectMenu = new OCA.Files.FileMultiSelectMenu(options.multiSelectMenu); | |||
this.$el.find('#selectedActionsList').append(this.fileMultiSelectMenu.$el); | |||
} | |||
if (options.sorting) { | |||
this.setSort(options.sorting.mode, options.sorting.direction, false, false); | |||
@@ -363,16 +346,11 @@ | |||
this.$el.on('show', _.bind(this._onShow, this)); | |||
this.$el.on('urlChanged', _.bind(this._onUrlChanged, this)); | |||
this.$el.find('.select-all').click(_.bind(this._onClickSelectAll, this)); | |||
this.$el.find('.download').click(_.bind(this._onClickDownloadSelected, this)); | |||
this.$el.find('.copy-move').click(_.bind(this._onClickCopyMoveSelected, this)); | |||
this.$el.find('.delete-selected').click(_.bind(this._onClickDeleteSelected, this)); | |||
this.$el.find('.actions-selected').click(function () { | |||
self.fileSelectionMenu.show(self); | |||
self.fileMultiSelectMenu.show(self); | |||
return false; | |||
}); | |||
this.$el.find('.selectedActions a').tooltip({placement:'top'}); | |||
this.$container.on('scroll', _.bind(this._onScroll, this)); | |||
if (options.scrollTo) { | |||
@@ -420,6 +398,22 @@ | |||
$('#app-content').off('appresized', this._onResize); | |||
}, | |||
multiSelectMenuClick: function (ev, action) { | |||
switch (action) { | |||
case 'delete': | |||
this._onClickDeleteSelected(ev) | |||
break; | |||
case 'download': | |||
this._onClickDownloadSelected(ev); | |||
break; | |||
case 'moveCopy': | |||
this._onClickCopyMoveSelected(ev); | |||
break; | |||
case 'restore': | |||
this._onClickRestoreSelected(ev); | |||
break; | |||
} | |||
}, | |||
/** | |||
* Initializes the file actions, set up listeners. | |||
* | |||
@@ -775,9 +769,11 @@ | |||
/** | |||
* Event handler for when clicking on "Download" for the selected files | |||
*/ | |||
_onClickDownloadSelected: function(event) { | |||
_onClickDownloadSelected: function() { | |||
var files; | |||
var self = this; | |||
var dir = this.getCurrentDirectory(); | |||
if (this.isAllSelected() && this.getSelectedFiles().length > 1) { | |||
files = OC.basename(dir); | |||
dir = OC.dirname(dir) || '/'; | |||
@@ -786,20 +782,16 @@ | |||
files = _.pluck(this.getSelectedFiles(), 'name'); | |||
} | |||
// TODO: Update | |||
var downloadFileaction = $('#selectedActionsList').find('.download'); | |||
// don't allow a second click on the download action | |||
if(downloadFileaction.hasClass('disabled')) { | |||
event.preventDefault(); | |||
return; | |||
if(this.fileMultiSelectMenu.isDisabled('download')) { | |||
return false; | |||
} | |||
this.fileMultiSelectMenu.toggleLoading('download', true); | |||
var disableLoadingState = function(){ | |||
OCA.Files.FileActions.updateFileActionSpinner(downloadFileaction, false); | |||
self.fileMultiSelectMenu.toggleLoading('download', false); | |||
}; | |||
OCA.Files.FileActions.updateFileActionSpinner(downloadFileaction, true); | |||
if(this.getSelectedFiles().length > 1) { | |||
OCA.Files.Files.handleDownload(this.getDownloadUrl(files, dir, true), disableLoadingState); | |||
} | |||
@@ -813,23 +805,20 @@ | |||
/** | |||
* Event handler for when clicking on "Move" for the selected files | |||
*/ | |||
_onClickCopyMoveSelected: function(event) { | |||
_onClickCopyMoveSelected: function() { | |||
var files; | |||
var self = this; | |||
files = _.pluck(this.getSelectedFiles(), 'name'); | |||
// TODO: Update | |||
var moveFileAction = $('#selectedActionsList').find('.move'); | |||
// don't allow a second click on the download action | |||
if(moveFileAction.hasClass('disabled')) { | |||
event.preventDefault(); | |||
return; | |||
if(this.fileMultiSelectMenu.isDisabled('moveCopy')) { | |||
return false; | |||
} | |||
self.fileMultiSelectMenu.toggleLoading('moveCopy', true); | |||
var disableLoadingState = function(){ | |||
OCA.Files.FileActions.updateFileActionSpinner(moveFileAction, false); | |||
self.fileMultiSelectMenu.toggleLoading('moveCopy', false); | |||
}; | |||
var actions = this.isSelectedMovable() ? OC.dialogs.FILEPICKER_TYPE_COPY_MOVE : OC.dialogs.FILEPICKER_TYPE_COPY; | |||
@@ -847,7 +836,7 @@ | |||
/** | |||
* Event handler for when clicking on "Delete" for the selected files | |||
*/ | |||
_onClickDeleteSelected: function(event) { | |||
_onClickDeleteSelected: function() { | |||
var files = null; | |||
if (!this.isAllSelected()) { | |||
files = _.pluck(this.getSelectedFiles(), 'name'); | |||
@@ -2922,14 +2911,14 @@ | |||
this.$el.find('table').addClass('multiselect'); | |||
this.fileSelectionMenu.toggleItemVisibility('download', !this.isSelectedDownloadable()); | |||
this.fileSelectionMenu.toggleItemVisibility('delete', !this.isSelectedDeletable()); | |||
this.fileSelectionMenu.toggleItemVisibility('moveCopy', !this.isSelectedCopiable()); | |||
this.fileMultiSelectMenu.toggleItemVisibility('download', !this.isSelectedDownloadable()); | |||
this.fileMultiSelectMenu.toggleItemVisibility('delete', !this.isSelectedDeletable()); | |||
this.fileMultiSelectMenu.toggleItemVisibility('moveCopy', !this.isSelectedCopiable()); | |||
if (this.isSelectedCopiable()) { | |||
if (this.isSelectedMovable()) { | |||
this.fileSelectionMenu.updateItemText('moveCopy', t('files', 'Move or copy')); | |||
this.fileMultiSelectMenu.updateItemText('moveCopy', t('files', 'Move or copy')); | |||
} else { | |||
this.fileSelectionMenu.updateItemText('moveCopy', t('files', 'Copy')); | |||
this.fileMultiSelectMenu.updateItemText('moveCopy', t('files', 'Copy')); | |||
} | |||
} | |||
} |
@@ -20,45 +20,15 @@ | |||
'<span class="no-icon"></span>' + | |||
'{{/if}}' + | |||
'<span class="label">{{displayName}}</span>' + | |||
'</li>' + | |||
'</a></li>' + | |||
'{{/each}}' + | |||
'</ul>'; | |||
var FileSelectionMenu = OC.Backbone.View.extend({ | |||
var FileMultiSelectMenu = OC.Backbone.View.extend({ | |||
tagName: 'div', | |||
className: 'filesSelectMenu popovermenu bubble menu-center', | |||
_scopes: null, | |||
/** | |||
* Event handler whenever an action has been clicked within the menu | |||
* | |||
* @param {Object} event event object | |||
*/ | |||
_onClickAction: function(event) { | |||
var $target = $(event.currentTarget); | |||
if (!$target.hasClass('menuitem')) { | |||
$target = $target.closest('.menuitem'); | |||
} | |||
OC.hideMenus(); | |||
var action = $target.data('action'); | |||
if (!action) { | |||
return; | |||
} | |||
for (var i = 0; i !== this._scopes.length; ++i) { | |||
var name = this._scopes[i].name; | |||
var method = this._scopes[i].method; | |||
if (name === action) { | |||
method(event); | |||
break; | |||
} | |||
} | |||
}, | |||
initialize: function(menuItems) { | |||
console.log('init-fileseleectionmenu'); | |||
console.log(menuItems); | |||
this._scopes = menuItems; | |||
}, | |||
events: { | |||
@@ -84,7 +54,11 @@ | |||
this.render(); | |||
this.$el.removeClass('hidden'); | |||
if (window.innerWidth < 480) { | |||
this.$el.removeClass('menu-center').addClass('menu-right'); | |||
} else { | |||
this.$el.removeClass('menu-right').addClass('menu-center'); | |||
} | |||
OC.showMenu(null, this.$el); | |||
return false; | |||
}, | |||
@@ -93,8 +67,44 @@ | |||
}, | |||
updateItemText: function (itemName, translation) { | |||
this.$el.find('.item-' + itemName).find('label').text(translation); | |||
}, | |||
toggleLoading: function (itemName, showLoading) { | |||
var $actionElement = this.$el.find('.item-' + itemName); | |||
if ($actionElement.length === 0) { | |||
return; | |||
} | |||
var $icon = $actionElement.find('.icon'); | |||
if (showLoading) { | |||
var $loadingIcon = $('<span class="icon icon-loading-small"></span>'); | |||
$icon.after($loadingIcon); | |||
$icon.addClass('hidden'); | |||
$actionElement.addClass('disabled'); | |||
} else { | |||
$actionElement.find('.icon-loading-small').remove(); | |||
$actionElement.find('.icon').removeClass('hidden'); | |||
$actionElement.removeClass('disabled'); | |||
} | |||
}, | |||
isDisabled: function (itemName) { | |||
var $actionElement = this.$el.find('.item-' + itemName); | |||
return $actionElement.hasClass('disabled'); | |||
}, | |||
/** | |||
* Event handler whenever an action has been clicked within the menu | |||
* | |||
* @param {Object} event event object | |||
*/ | |||
_onClickAction: function (event) { | |||
var $target = $(event.currentTarget); | |||
if (!$target.hasClass('menuitem')) { | |||
$target = $target.closest('.menuitem'); | |||
} | |||
OC.hideMenus(); | |||
this._context.multiSelectMenuClick(event, $target.data('action')); | |||
return false; | |||
} | |||
}); | |||
OCA.Files.FileSelectionMenu = FileSelectionMenu; | |||
})(OC, OCA); | |||
OCA.Files.FileMultiSelectMenu = FileMultiSelectMenu; | |||
})(OC, OCA); |
@@ -6,7 +6,7 @@ | |||
"jquery-visibility.js", | |||
"fileinfomodel.js", | |||
"filesummary.js", | |||
"fileselectionmenu.js", | |||
"filemultiselectmenu.js", | |||
"breadcrumb.js", | |||
"filelist.js", | |||
"search.js", |
@@ -28,10 +28,12 @@ | |||
<a id="modified" class="columntitle" | |||
data-sort="mtime"><span><?php p($l->t('Modified')); ?></span><span | |||
class="sort-indicator"></span></a> | |||
<span class="selectedActions"><a href="" class="delete-selected"> | |||
<span><?php p($l->t('Delete')) ?></span> | |||
<span class="icon icon-delete"></span> | |||
</a></span> | |||
<span class="selectedActions"> | |||
<a href="" class="delete-selected"> | |||
<span class="icon icon-delete"></span> | |||
<span><?php p($l->t('Delete')) ?></span> | |||
</a> | |||
</span> | |||
</th> | |||
</tr> | |||
</thead> |
@@ -13,7 +13,6 @@ | |||
<h2><?php p($l->t('No entries found in this folder')); ?></h2> | |||
<p></p> | |||
</div> | |||
<table id="filestable"> | |||
<thead> | |||
<tr> | |||
@@ -27,11 +26,13 @@ | |||
</th> | |||
<th id="headerDate" class="hidden column-mtime"> | |||
<a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Modified' )); ?></span><span class="sort-indicator"></span></a> | |||
<span class="selectedActions"><a href="" class="delete-selected"> | |||
<?php p($l->t('Delete'))?> | |||
<img class="svg" alt="" | |||
src="<?php print_unescaped(OCP\Template::image_path("core", "actions/delete.svg")); ?>" /> | |||
</a></span> | |||
<span class="selectedActions"> | |||
<a href="" class="delete-selected"> | |||
<img class="svg" alt="" | |||
src="<?php print_unescaped(OCP\Template::image_path("core", "actions/delete.svg")); ?>" /> | |||
<?php p($l->t('Delete'))?> | |||
</a> | |||
</span> | |||
</th> | |||
</tr> | |||
</thead> |
@@ -30,7 +30,19 @@ OCA.Trashbin.App = { | |||
fileActions: this._createFileActions(), | |||
detailsViewEnabled: false, | |||
scrollTo: urlParams.scrollto, | |||
config: OCA.Files.App.getFilesConfig() | |||
config: OCA.Files.App.getFilesConfig(), | |||
multiSelectMenu: [ | |||
{ | |||
name: 'restore', | |||
displayName: t('files', 'Restore'), | |||
iconClass: 'icon-history', | |||
}, | |||
{ | |||
name: 'delete', | |||
displayName: t('files', 'Delete'), | |||
iconClass: 'icon-delete', | |||
} | |||
] | |||
} | |||
); | |||
}, |
@@ -31,25 +31,15 @@ | |||
<div id="headerName-container"> | |||
<a class="name sort columntitle" data-sort="name"><span><?php p($l->t( 'Name' )); ?></span><span class="sort-indicator"></span></a> | |||
<span id="selectedActionsList" class='selectedActions'> | |||
<a href="" class="undelete"> | |||
<span class="icon icon-history"></span> | |||
<span><?php p($l->t('Restore'))?></span> | |||
</a> | |||
<a href="" class="delete-selected"> | |||
<span class="icon icon-delete"></span> | |||
<span><?php p($l->t('Delete'))?></span> | |||
<a href="" class="actions-selected"> | |||
<span class="icon icon-more"></span> | |||
<span><?php p($l->t('Actions'))?></span> | |||
</a> | |||
</span> | |||
</div> | |||
</th> | |||
<th id="headerDate" class="hidden column-mtime"> | |||
<a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Deleted' )); ?></span><span class="sort-indicator"></span></a> | |||
<span class="selectedActions"> | |||
<a href="" class="delete-selected"> | |||
<span><?php p($l->t('Delete'))?></span> | |||
<span class="icon icon-delete"></span> | |||
</a> | |||
</span> | |||
</th> | |||
</tr> | |||
</thead> |