summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files/css/files.scss28
-rw-r--r--apps/files/css/mobile.scss11
-rw-r--r--apps/files/js/app.js19
-rw-r--r--apps/files/js/fileactions.js12
-rw-r--r--apps/files/js/filelist.js89
-rw-r--r--apps/files/js/filemultiselectmenu.js112
-rw-r--r--apps/files/js/merged-index.json1
-rw-r--r--apps/files/templates/list.php28
-rw-r--r--apps/files/templates/recentlist.php10
-rw-r--r--apps/files/templates/simplelist.php13
-rw-r--r--apps/files/tests/js/filelistSpec.js62
-rw-r--r--apps/files_trashbin/js/app.js14
-rw-r--r--apps/files_trashbin/js/filelist.js20
-rw-r--r--apps/files_trashbin/templates/index.php16
-rw-r--r--apps/files_trashbin/tests/js/filelistSpec.js49
-rw-r--r--core/css/mobile.scss2
16 files changed, 338 insertions, 148 deletions
diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss
index d2d810c1e6c..38c74d242bc 100644
--- a/apps/files/css/files.scss
+++ b/apps/files/css/files.scss
@@ -176,9 +176,11 @@ table th .columntitle {
-moz-box-sizing: border-box;
vertical-align: middle;
}
+table.multiselect th .columntitle {
+ display: inline-block;
+}
table th .columntitle.name {
padding-left: 5px;
- padding-right: 80px;
margin-left: 50px;
}
@@ -246,7 +248,7 @@ table th.column-last, table td.column-last {
}
table.multiselect thead {
position: fixed;
- top: 89px;
+ top: 94px;
z-index: 55;
-moz-box-sizing: border-box;
box-sizing: border-box;
@@ -474,19 +476,19 @@ a.action > img {
/* Actions for selected files */
.selectedActions {
- position: absolute;
- top: 0;
- right: 0;
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+}
+.selectedActions.hidden {
+ display: none;
}
.selectedActions a {
display: inline;
- font-size: 11px;
line-height: 50px;
- padding: 18px 5px;
-}
-.selectedActions a.delete-selected {
- padding-right: 15px;
+ padding: 16px 5px;
}
+
.selectedActions a.hidden {
display: none;
}
@@ -495,9 +497,9 @@ 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;
+
+.selectedActions .actions-selected .icon-more {
+ margin-top: -3px;
}
#fileList td a {
diff --git a/apps/files/css/mobile.scss b/apps/files/css/mobile.scss
index c5bb8193924..a53066c4452 100644
--- a/apps/files/css/mobile.scss
+++ b/apps/files/css/mobile.scss
@@ -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 {
@@ -71,7 +67,10 @@ table.dragshadow {
}
@media only screen and (max-width: 480px) {
/* Only show icons */
- table th .selectedActions a span:not(.icon) {
+ table th .selectedActions {
+ float: right;
+ }
+ table th .selectedActions > a span:not(.icon) {
display: none;
}
diff --git a/apps/files/js/app.js b/apps/files/js/app.js
index 6e4e8c1b136..6a21bce975b 100644
--- a/apps/files/js/app.js
+++ b/apps/files/js/app.js
@@ -88,6 +88,23 @@
allowLegacyActions: true,
scrollTo: urlParams.scrollto,
filesClient: OC.Files.getClient(),
+ multiSelectMenu: [
+ {
+ name: 'copyMove',
+ 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);
diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js
index 4c0ccaf6451..3623663ed6c 100644
--- a/apps/files/js/fileactions.js
+++ b/apps/files/js/fileactions.js
@@ -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');
}
};
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 307147076b2..c420e7212a0 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -126,7 +126,11 @@
* @type OCA.Files.FileActions
*/
fileActions: null,
-
+ /**
+ * File selection menu, defaults to OCA.Files.FileSelectionMenu
+ * @type OCA.Files.FileSelectionMenu
+ */
+ fileMultiSelectMenu: null,
/**
* Whether selection is allowed, checkboxes and selection overlay will
* be rendered
@@ -288,6 +292,12 @@
this.fileSummary = this._createSummary();
+ if (options.multiSelectMenu) {
+ this.fileMultiSelectMenu = new OCA.Files.FileMultiSelectMenu(options.multiSelectMenu);
+ this.fileMultiSelectMenu.render();
+ this.$el.find('.selectedActions').append(this.fileMultiSelectMenu.$el);
+ }
+
if (options.sorting) {
this.setSort(options.sorting.mode, options.sorting.direction, false, false);
} else {
@@ -336,11 +346,10 @@
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('.selectedActions a').tooltip({placement:'top'});
+ this.$el.find('.actions-selected').click(function () {
+ self.fileMultiSelectMenu.show(self);
+ return false;
+ });
this.$container.on('scroll', _.bind(this._onScroll, this));
@@ -365,6 +374,7 @@
}
}
+
OC.Plugins.attach('OCA.Files.FileList', this);
},
@@ -388,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 'copyMove':
+ this._onClickCopyMoveSelected(ev);
+ break;
+ case 'restore':
+ this._onClickRestoreSelected(ev);
+ break;
+ }
+ },
/**
* Initializes the file actions, set up listeners.
*
@@ -745,7 +771,9 @@
*/
_onClickDownloadSelected: function(event) {
var files;
+ var self = this;
var dir = this.getCurrentDirectory();
+
if (this.isAllSelected() && this.getSelectedFiles().length > 1) {
files = OC.basename(dir);
dir = OC.dirname(dir) || '/';
@@ -754,19 +782,16 @@
files = _.pluck(this.getSelectedFiles(), 'name');
}
- 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);
}
@@ -774,7 +799,7 @@
var first = this.getSelectedFiles()[0];
OCA.Files.Files.handleDownload(this.getDownloadUrl(first.name, dir, true), disableLoadingState);
}
- return false;
+ event.preventDefault();
},
/**
@@ -786,20 +811,18 @@
files = _.pluck(this.getSelectedFiles(), 'name');
- 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('copyMove')) {
+ return false;
}
var disableLoadingState = function(){
- OCA.Files.FileActions.updateFileActionSpinner(moveFileAction, false);
+ self.fileMultiSelectMenu.toggleLoading('copyMove', false);
};
var actions = this.isSelectedMovable() ? OC.dialogs.FILEPICKER_TYPE_COPY_MOVE : OC.dialogs.FILEPICKER_TYPE_COPY;
OC.dialogs.filepicker(t('files', 'Target folder'), function(targetPath, type) {
+ self.fileMultiSelectMenu.toggleLoading('copyMove', true);
if (type === OC.dialogs.FILEPICKER_TYPE_COPY) {
self.copy(files, targetPath, disableLoadingState);
}
@@ -807,7 +830,7 @@
self.move(files, targetPath, disableLoadingState);
}
}, false, "httpd/unix-directory", true, actions);
- return false;
+ event.preventDefault();
},
/**
@@ -820,7 +843,6 @@
}
this.do_delete(files);
event.preventDefault();
- return false;
},
/**
@@ -2885,19 +2907,20 @@
this.$el.find('#headerName a.name>span:first').text(selection);
this.$el.find('#modified a>span:first').text('');
this.$el.find('table').addClass('multiselect');
- this.$el.find('.selectedActions .download').toggleClass('hidden', !this.isSelectedDownloadable());
- this.$el.find('.delete-selected').toggleClass('hidden', !this.isSelectedDeletable());
-
- var $copyMove = this.$el.find('.selectedActions .copy-move');
- if (this.isSelectedCopiable()) {
- $copyMove.toggleClass('hidden', false);
- if (this.isSelectedMovable()) {
- $copyMove.find('.label').text(t('files', 'Move or copy'));
+
+ if (this.fileMultiSelectMenu) {
+ this.fileMultiSelectMenu.toggleItemVisibility('download', this.isSelectedDownloadable());
+ this.fileMultiSelectMenu.toggleItemVisibility('delete', this.isSelectedDeletable());
+ this.fileMultiSelectMenu.toggleItemVisibility('copyMove', this.isSelectedCopiable());
+ if (this.isSelectedCopiable()) {
+ if (this.isSelectedMovable()) {
+ this.fileMultiSelectMenu.updateItemText('copyMove', t('files', 'Move or copy'));
+ } else {
+ this.fileMultiSelectMenu.updateItemText('copyMove', t('files', 'Copy'));
+ }
} else {
- $copyMove.find('.label').text(t('files', 'Copy'));
+ this.fileMultiSelectMenu.toggleItemVisibility('copyMove', false);
}
- } else {
- $copyMove.toggleClass('hidden', true);
}
}
},
diff --git a/apps/files/js/filemultiselectmenu.js b/apps/files/js/filemultiselectmenu.js
new file mode 100644
index 00000000000..d587d1fbdb2
--- /dev/null
+++ b/apps/files/js/filemultiselectmenu.js
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+ var TEMPLATE_MENU =
+ '<ul>' +
+ '{{#each items}}' +
+ '<li class="item-{{name}}">' +
+ '<a href="#" class="menuitem action {{name}} permanent" data-action="{{name}}">' +
+ '{{#if iconClass}}' +
+ '<span class="icon {{iconClass}}"></span>' +
+ '{{else}}' +
+ '<span class="no-icon"></span>' +
+ '{{/if}}' +
+ '<span class="label">{{displayName}}</span>' +
+ '</a></li>' +
+ '{{/each}}' +
+ '</ul>';
+
+ var FileMultiSelectMenu = OC.Backbone.View.extend({
+ tagName: 'div',
+ className: 'filesSelectMenu popovermenu bubble menu-center',
+ _scopes: null,
+ initialize: function(menuItems) {
+ this._scopes = menuItems;
+ },
+ events: {
+ 'click a.action': '_onClickAction'
+ },
+ template: Handlebars.compile(TEMPLATE_MENU),
+ /**
+ * Renders the menu with the currently set items
+ */
+ render: function() {
+ this.$el.html(this.template({
+ items: this._scopes
+ }));
+ },
+ /**
+ * Displays the menu under the given element
+ *
+ * @param {OCA.Files.FileActionContext} context context
+ * @param {Object} $trigger trigger element
+ */
+ show: function(context) {
+ this._context = context;
+ 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;
+ },
+ toggleItemVisibility: function (itemName, show) {
+ if (show) {
+ this.$el.find('.item-' + itemName).removeClass('hidden');
+ } else {
+ this.$el.find('.item-' + itemName).addClass('hidden');
+ }
+ },
+ 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.FileMultiSelectMenu = FileMultiSelectMenu;
+})(OC, OCA);
diff --git a/apps/files/js/merged-index.json b/apps/files/js/merged-index.json
index 127bbb46b29..cd7e72e1a51 100644
--- a/apps/files/js/merged-index.json
+++ b/apps/files/js/merged-index.json
@@ -6,6 +6,7 @@
"jquery-visibility.js",
"fileinfomodel.js",
"filesummary.js",
+ "filemultiselectmenu.js",
"breadcrumb.js",
"filelist.js",
"search.js",
diff --git a/apps/files/templates/list.php b/apps/files/templates/list.php
index e6b1e54d389..9cae72a176f 100644
--- a/apps/files/templates/list.php
+++ b/apps/files/templates/list.php
@@ -49,20 +49,16 @@
</th>
<th id='headerName' class="hidden column-name">
<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="copy-move">
- <span class="icon icon-external"></span>
- <span class="label"><?php p($l->t('Move or copy'))?></span>
- </a>
- <a href="" class="download">
- <span class="icon icon-download"></span>
- <span><?php p($l->t('Download'))?></span>
- </a>
- <a href="" class="delete-selected">
- <span class="icon icon-delete"></span>
- <span><?php p($l->t('Delete'))?></span>
- </a>
+ <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="actions-selected">
+ <span class="icon icon-more"></span>
+ <span><?php p($l->t('Actions'))?></span>
+ </a>
</span>
</div>
</th>
@@ -71,10 +67,6 @@
</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">
- <span><?php p($l->t('Delete'))?></span>
- <span class="icon icon-delete"></span>
- </a></span>
</th>
</tr>
</thead>
diff --git a/apps/files/templates/recentlist.php b/apps/files/templates/recentlist.php
index 6c271a07f5f..cfdb95c80a0 100644
--- a/apps/files/templates/recentlist.php
+++ b/apps/files/templates/recentlist.php
@@ -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>
diff --git a/apps/files/templates/simplelist.php b/apps/files/templates/simplelist.php
index 1dc927c9b59..78adb21922f 100644
--- a/apps/files/templates/simplelist.php
+++ b/apps/files/templates/simplelist.php
@@ -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>
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index 1b26a468172..efaf9968def 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -94,9 +94,7 @@ describe('OCA.Files.FileList tests', function() {
'<input type="checkbox" id="select_all_files" class="select-all checkbox">' +
'<a class="name columntitle" data-sort="name"><span>Name</span><span class="sort-indicator"></span></a>' +
'<span id="selectedActionsList" class="selectedActions hidden">' +
- '<a href class="copy-move"><span class="label">Move or copy</span></a>' +
- '<a href class="download"><img src="actions/download.svg">Download</a>' +
- '<a href class="delete-selected">Delete</a></span>' +
+ '<a href class="actions-selected"><span class="icon icon-more"></span><span>Actions</span></a>' +
'</th>' +
'<th class="hidden column-size"><a class="columntitle" data-sort="size"><span class="sort-indicator"></span></a></th>' +
'<th class="hidden column-mtime"><a class="columntitle" data-sort="mtime"><span class="sort-indicator"></span></a></th>' +
@@ -161,7 +159,22 @@ describe('OCA.Files.FileList tests', function() {
fileList = new OCA.Files.FileList($('#app-content-files'), {
filesClient: filesClient,
config: filesConfig,
- enableUpload: true
+ enableUpload: true,
+ multiSelectMenu: [{
+ name: 'copyMove',
+ 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',
+ }]
});
});
afterEach(function() {
@@ -2100,41 +2113,41 @@ describe('OCA.Files.FileList tests', function() {
fileList.setFiles(testFiles);
$('#permissions').val(OC.PERMISSION_READ | OC.PERMISSION_UPDATE);
$('.select-all').click();
- expect(fileList.$el.find('.selectedActions .copy-move').hasClass('hidden')).toEqual(false);
- expect(fileList.$el.find('.selectedActions .copy-move .label').text()).toEqual('Move or copy');
+ expect(fileList.$el.find('.selectedActions .item-copyMove').hasClass('hidden')).toEqual(false);
+ expect(fileList.$el.find('.selectedActions .item-copyMove .label').text()).toEqual('Move or copy');
testFiles[0].permissions = OC.PERMISSION_READ;
$('.select-all').click();
fileList.setFiles(testFiles);
$('.select-all').click();
- expect(fileList.$el.find('.selectedActions .copy-move').hasClass('hidden')).toEqual(false);
- expect(fileList.$el.find('.selectedActions .copy-move .label').text()).toEqual('Copy');
+ expect(fileList.$el.find('.selectedActions .item-copyMove').hasClass('hidden')).toEqual(false);
+ expect(fileList.$el.find('.selectedActions .item-copyMove .label').text()).toEqual('Copy');
testFiles[0].permissions = OC.PERMISSION_NONE;
$('.select-all').click();
fileList.setFiles(testFiles);
$('.select-all').click();
- expect(fileList.$el.find('.selectedActions .copy-move').hasClass('hidden')).toEqual(true);
+ expect(fileList.$el.find('.selectedActions .item-copyMove').hasClass('hidden')).toEqual(true);
});
it('show doesnt show the download action if one or more files are not downloadable', function () {
fileList.setFiles(testFiles);
$('#permissions').val(OC.PERMISSION_READ | OC.PERMISSION_UPDATE);
$('.select-all').click();
- expect(fileList.$el.find('.selectedActions .download').hasClass('hidden')).toEqual(false);
+ expect(fileList.$el.find('.selectedActions .item-download').hasClass('hidden')).toEqual(false);
testFiles[0].permissions = OC.PERMISSION_UPDATE;
$('.select-all').click();
fileList.setFiles(testFiles);
$('.select-all').click();
- expect(fileList.$el.find('.selectedActions .download').hasClass('hidden')).toEqual(true);
+ expect(fileList.$el.find('.selectedActions .item-download').hasClass('hidden')).toEqual(true);
});
it('show doesnt show the delete action if one or more files are not deletable', function () {
fileList.setFiles(testFiles);
$('#permissions').val(OC.PERMISSION_READ | OC.PERMISSION_DELETE);
$('.select-all').click();
- expect(fileList.$el.find('.delete-selected').hasClass('hidden')).toEqual(false);
+ expect(fileList.$el.find('.selectedActions .item-delete').hasClass('hidden')).toEqual(false);
testFiles[0].permissions = OC.PERMISSION_READ;
$('.select-all').click();
fileList.setFiles(testFiles);
$('.select-all').click();
- expect(fileList.$el.find('.delete-selected').hasClass('hidden')).toEqual(true);
+ expect(fileList.$el.find('.selectedActions .item-delete').hasClass('hidden')).toEqual(true);
});
});
describe('Actions', function() {
@@ -2219,8 +2232,12 @@ describe('OCA.Files.FileList tests', function() {
});
});
describe('Download', function() {
+ beforeEach(function() {
+ fileList.$el.find('.actions-selected').click();
+ });
+
it('Opens download URL when clicking "Download"', function() {
- $('.selectedActions .download').click();
+ $('.selectedActions .filesSelectMenu .download').click();
expect(redirectStub.calledOnce).toEqual(true);
expect(redirectStub.getCall(0).args[0]).toContain(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22One.txt%22%2C%22Three.pdf%22%2C%22somedir%22%5D');
redirectStub.restore();
@@ -2228,28 +2245,37 @@ describe('OCA.Files.FileList tests', function() {
it('Downloads root folder when all selected in root folder', function() {
$('#dir').val('/');
$('.select-all').click();
- $('.selectedActions .download').click();
+ $('.selectedActions .filesSelectMenu .download').click();
expect(redirectStub.calledOnce).toEqual(true);
expect(redirectStub.getCall(0).args[0]).toContain(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=');
});
it('Downloads parent folder when all selected in subfolder', function() {
$('.select-all').click();
- $('.selectedActions .download').click();
+ $('.selectedActions .filesSelectMenu .download').click();
expect(redirectStub.calledOnce).toEqual(true);
expect(redirectStub.getCall(0).args[0]).toContain(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=subdir');
});
+
+ afterEach(function() {
+ fileList.$el.find('.actions-selected').click();
+ });
});
+
describe('Delete', function() {
var deleteStub, deferredDelete;
beforeEach(function() {
deferredDelete = $.Deferred();
deleteStub = sinon.stub(filesClient, 'remove').returns(deferredDelete.promise());
+ fileList.$el.find('.actions-selected').click();
});
+
afterEach(function() {
+ fileList.$el.find('.actions-selected').click();
deleteStub.restore();
});
+
it('Deletes selected files when "Delete" clicked', function() {
- $('.selectedActions .delete-selected').click();
+ $('.selectedActions .filesSelectMenu .delete').click();
expect(deleteStub.callCount).toEqual(3);
expect(deleteStub.getCall(0).args[0]).toEqual('/subdir/One.txt');
@@ -2265,7 +2291,7 @@ describe('OCA.Files.FileList tests', function() {
});
it('Deletes all files when all selected when "Delete" clicked', function() {
$('.select-all').click();
- $('.selectedActions .delete-selected').click();
+ $('.selectedActions .filesSelectMenu .delete').click();
expect(deleteStub.callCount).toEqual(4);
expect(deleteStub.getCall(0).args[0]).toEqual('/subdir/One.txt');
diff --git a/apps/files_trashbin/js/app.js b/apps/files_trashbin/js/app.js
index fd3d5db32ff..002c01bf967 100644
--- a/apps/files_trashbin/js/app.js
+++ b/apps/files_trashbin/js/app.js
@@ -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',
+ }
+ ]
}
);
},
diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js
index 4846c2361fe..324e4d8a7e0 100644
--- a/apps/files_trashbin/js/filelist.js
+++ b/apps/files_trashbin/js/filelist.js
@@ -153,7 +153,6 @@
}
this.fileSummary.update();
this.updateEmptyContent();
- this.enableActions();
},
_onClickRestoreSelected: function(event) {
@@ -162,7 +161,7 @@
var allFiles = this.$el.find('.select-all').is(':checked');
var files = [];
var params = {};
- this.disableActions();
+ this.fileMultiSelectMenu.toggleLoading('restore', true);
if (allFiles) {
this.showMask();
params = {
@@ -192,13 +191,14 @@
self.hideMask();
// simply remove all files
self.setFiles([]);
- self.enableActions();
}
else {
self._removeCallback(result);
}
+ self.fileMultiSelectMenu.toggleLoading('restore', false);
}
);
+ event.preventDefault();
},
_onClickDeleteSelected: function(event) {
@@ -221,7 +221,7 @@
};
}
- this.disableActions();
+ this.fileMultiSelectMenu.toggleLoading('delete', true);
if (allFiles) {
this.showMask();
}
@@ -242,11 +242,11 @@
self.hideMask();
// simply remove all files
self.setFiles([]);
- self.enableActions();
}
else {
self._removeCallback(result);
}
+ self.fileMultiSelectMenu.toggleLoading('delete', false);
}
);
},
@@ -268,16 +268,6 @@
return '#';
},
- enableActions: function() {
- this.$el.find('.action').css('display', 'inline');
- this.$el.find('input:checkbox').removeClass('u-hidden');
- },
-
- disableActions: function() {
- this.$el.find('.action').css('display', 'none');
- this.$el.find('input:checkbox').addClass('u-hidden');
- },
-
updateStorageStatistics: function() {
// no op because the trashbin doesn't have
// storage info like free space / used space
diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php
index a4459947d09..dd24abb5de1 100644
--- a/apps/files_trashbin/templates/index.php
+++ b/apps/files_trashbin/templates/index.php
@@ -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>
diff --git a/apps/files_trashbin/tests/js/filelistSpec.js b/apps/files_trashbin/tests/js/filelistSpec.js
index 04ff243d07b..c5b1018856b 100644
--- a/apps/files_trashbin/tests/js/filelistSpec.js
+++ b/apps/files_trashbin/tests/js/filelistSpec.js
@@ -46,8 +46,8 @@ describe('OCA.Trashbin.FileList tests', function() {
'<input type="checkbox" id="select_all_trash" class="select-all">' +
'<span class="name">Name</span>' +
'<span class="selectedActions hidden">' +
- '<a href class="undelete">Restore</a>' +
- '<a href class="delete-selected">Delete</a></span>' +
+ '<a href="" class="actions-selected"><span class="icon icon-more"></span><span>Actions</span>' +
+ '</span>' +
'</th></tr></thead>' +
'<tbody id="fileList"></tbody>' +
'<tfoot></tfoot>' +
@@ -90,7 +90,18 @@ describe('OCA.Trashbin.FileList tests', function() {
var fileActions = OCA.Trashbin.App._createFileActions(fileList);
fileList = new OCA.Trashbin.FileList(
$('#app-content-trashbin'), {
- fileActions: fileActions
+ fileActions: fileActions,
+ multiSelectMenu: [{
+ name: 'restore',
+ displayName: t('files', 'Restore'),
+ iconClass: 'icon-history',
+ },
+ {
+ name: 'delete',
+ displayName: t('files', 'Delete'),
+ iconClass: 'icon-delete',
+ }
+ ]
}
);
});
@@ -260,33 +271,41 @@ describe('OCA.Trashbin.FileList tests', function() {
fileList.findFileEl('One.txt.d11111').find('input:checkbox').click();
fileList.findFileEl('Three.pdf.d33333').find('input:checkbox').click();
fileList.findFileEl('somedir.d99999').find('input:checkbox').click();
+ fileList.$el.find('.actions-selected').click();
+ });
+
+ afterEach(function() {
+ fileList.$el.find('.actions-selected').click();
});
+
describe('Delete', function() {
it('Shows trashbin actions', function() {
// visible because a few files were selected
expect($('.selectedActions').is(':visible')).toEqual(true);
- expect($('.selectedActions .delete-selected').is(':visible')).toEqual(true);
- expect($('.selectedActions .undelete').is(':visible')).toEqual(true);
+ expect($('.selectedActions .item-delete').is(':visible')).toEqual(true);
+ expect($('.selectedActions .item-restore').is(':visible')).toEqual(true);
// check
fileList.$el.find('.select-all').click();
// stays visible
expect($('.selectedActions').is(':visible')).toEqual(true);
- expect($('.selectedActions .delete-selected').is(':visible')).toEqual(true);
- expect($('.selectedActions .undelete').is(':visible')).toEqual(true);
+ expect($('.selectedActions .item-delete').is(':visible')).toEqual(true);
+ expect($('.selectedActions .item-restore').is(':visible')).toEqual(true);
// uncheck
fileList.$el.find('.select-all').click();
// becomes hidden now
expect($('.selectedActions').is(':visible')).toEqual(false);
- expect($('.selectedActions .delete-selected').is(':visible')).toEqual(false);
- expect($('.selectedActions .undelete').is(':visible')).toEqual(false);
+ expect($('.selectedActions .item-delete').is(':visible')).toEqual(false);
+ expect($('.selectedActions .item-restore').is(':visible')).toEqual(false);
});
it('Deletes selected files when "Delete" clicked', function() {
var request;
- $('.selectedActions .delete-selected').click();
+ var $deleteLink = $('.selectedActions .filesSelectMenu .delete');
+ $deleteLink.click();
+ expect($deleteLink.find('.icon-loading-small').length).toEqual(1);
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_trashbin/ajax/delete.php');
@@ -306,6 +325,7 @@ describe('OCA.Trashbin.FileList tests', function() {
}
})
);
+ expect($deleteLink.find('.icon-loading-small').length).toEqual(0);
expect(fileList.findFileEl('One.txt.d11111').length).toEqual(0);
expect(fileList.findFileEl('Three.pdf.d33333').length).toEqual(0);
expect(fileList.findFileEl('somedir.d99999').length).toEqual(0);
@@ -314,7 +334,7 @@ describe('OCA.Trashbin.FileList tests', function() {
it('Deletes all files when all selected when "Delete" clicked', function() {
var request;
$('.select-all').click();
- $('.selectedActions .delete-selected').click();
+ $('.selectedActions .filesSelectMenu .delete').click();
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_trashbin/ajax/delete.php');
@@ -331,7 +351,9 @@ describe('OCA.Trashbin.FileList tests', function() {
describe('Restore', function() {
it('Restores selected files when "Restore" clicked', function() {
var request;
- $('.selectedActions .undelete').click();
+ var $restoreLink = $('.selectedActions .filesSelectMenu .restore');
+ $restoreLink.click();
+ expect($restoreLink.find('.icon-loading-small').length).toEqual(1);
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_trashbin/ajax/undelete.php');
@@ -351,6 +373,7 @@ describe('OCA.Trashbin.FileList tests', function() {
}
})
);
+ expect($restoreLink.find('.icon-loading-small').length).toEqual(0);
expect(fileList.findFileEl('One.txt.d11111').length).toEqual(0);
expect(fileList.findFileEl('Three.pdf.d33333').length).toEqual(0);
expect(fileList.findFileEl('somedir.d99999').length).toEqual(0);
@@ -359,7 +382,7 @@ describe('OCA.Trashbin.FileList tests', function() {
it('Restores all files when all selected when "Restore" clicked', function() {
var request;
$('.select-all').click();
- $('.selectedActions .undelete').click();
+ $('.selectedActions .filesSelectMenu .restore').click();
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_trashbin/ajax/undelete.php');
diff --git a/core/css/mobile.scss b/core/css/mobile.scss
index cfc8c002e17..239876223d5 100644
--- a/core/css/mobile.scss
+++ b/core/css/mobile.scss
@@ -67,7 +67,7 @@
#app-navigation-toggle {
position: fixed;
display: inline-block !important;
- top: 45px;
+ top: 50px;
left: 0;
width: 44px;
height: 44px;