diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files/css/files.scss | 100 | ||||
-rw-r--r-- | apps/files/css/mobile.scss | 4 | ||||
-rw-r--r-- | apps/files/js/fileactions.js | 13 | ||||
-rw-r--r-- | apps/files/js/fileactionsmenu.js | 5 | ||||
-rw-r--r-- | apps/files/js/filelist.js | 49 | ||||
-rw-r--r-- | apps/files/js/tagsplugin.js | 75 | ||||
-rw-r--r-- | apps/files/templates/list.php | 10 | ||||
-rw-r--r-- | apps/files/tests/js/fileactionsmenuSpec.js | 28 | ||||
-rw-r--r-- | apps/files/tests/js/filelistSpec.js | 30 | ||||
-rw-r--r-- | apps/files/tests/js/tagspluginspec.js | 48 | ||||
-rw-r--r-- | apps/files_trashbin/templates/index.php | 10 |
11 files changed, 227 insertions, 145 deletions
diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss index 8ae8fac6c21..c03b1ce6fad 100644 --- a/apps/files/css/files.scss +++ b/apps/files/css/files.scss @@ -230,9 +230,6 @@ table th#headerName { position: relative; height: 50px; } -.has-favorites #headerName-container { - padding-left: 50px; -} table th#headerSize, table td.filesize { text-align: right; @@ -294,7 +291,12 @@ table td.filename a.name { line-height: 50px; padding: 0; } -table td.filename label.icon-loading-small { +table td.filename .thumbnail-wrapper { + position: absolute; + width: 50px; + height: 50px; +} +table td.filename .thumbnail-wrapper.icon-loading-small { &:after { z-index: 10; } @@ -306,10 +308,10 @@ table td.filename .thumbnail { display: inline-block; width: 32px; height: 32px; + background-size: 32px; margin-left: 9px; margin-top: 9px; cursor: pointer; - float: left; position: absolute; z-index: 4; } @@ -319,12 +321,9 @@ table td.filename input.filename { margin-left: 48px; cursor: text; } -.has-favorites table td.filename input.filename { - margin-left: 52px; -} table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; } -table td.filename .nametext, .uploadtext, .modified, .column-last>span:first-child { float:left; padding:15px 0; } +table td.filename .nametext, .modified, .column-last>span:first-child { float:left; padding:15px 0; } .modified, .column-last>span:first-child { position: relative; @@ -336,22 +335,23 @@ table td.filename .nametext, .uploadtext, .modified, .column-last>span:first-chi /* TODO fix usability bug (accidental file/folder selection) */ table td.filename .nametext { position: absolute; - left: 55px; padding: 0; + padding-left: 55px; overflow: hidden; text-overflow: ellipsis; width: 70%; max-width: 800px; height: 100%; + z-index: 10; +} +table td.filename .uploadtext { + position: absolute; + left: 55px; } /* ellipsis on file names */ table td.filename .nametext .innernametext { max-width: calc(100% - 100px) !important; } -.has-favorites #fileList td.filename a.name { - left: 50px; - margin-right: 50px; -} .hide-hidden-files #fileList tr.hidden-file, .hide-hidden-files #fileList tr.hidden-file.dragging { @@ -437,49 +437,27 @@ table td.filename .uploadtext { opacity: .5; } +table td.selection { + padding: 0; +} + /* File checkboxes */ -#fileList tr td.filename>.selectCheckBox + label:before { - opacity: 0; - position: absolute; - bottom: 4px; - right: 0; - z-index: 10; +#fileList tr td.selection>.selectCheckBox + label:before { + opacity: 0.3; } -/* Show checkbox when hovering, checked, or selected */ -#fileList tr:hover td.filename>.selectCheckBox + label:before, -#fileList tr:focus td.filename>.selectCheckBox + label:before, -#fileList tr td.filename>.selectCheckBox:checked + label:before, -#fileList tr.selected td.filename>.selectCheckBox + label:before { +/* Show checkbox with full opacity when hovering, checked, or selected */ +#fileList tr:hover td.selection>.selectCheckBox + label:before, +#fileList tr:focus td.selection>.selectCheckBox + label:before, +#fileList tr td.selection>.selectCheckBox:checked + label:before, +#fileList tr.selected td.selection>.selectCheckBox + label:before { opacity: 1; } /* Use label to have bigger clickable size for checkbox */ -#fileList tr td.filename>.selectCheckBox + label, +#fileList tr td.selection>.selectCheckBox + label, .select-all + label { - background-position: 30px 30px; - height: 50px; - position: absolute; - width: 50px; - z-index: 5; -} -#fileList tr td.filename>.selectCheckBox { - /* sometimes checkbox height is bigger (KDE/Qt), so setting to absolute - * to prevent it to increase the height */ - position: absolute; - z-index: 10; -} -.select-all + label { - top: 0; -} -.select-all + label:before { - position: absolute; - top: 18px; - left: 18px; - z-index: 10; -} -.has-favorites .select-all { - left: 68px; + padding: 16px; } #fileList tr td.filename { @@ -500,10 +478,11 @@ table td.filename .uploadtext { display: inline-block; float: left; } -#fileList tr td.filename .action-favorite { +#fileList tr td.filename .favorite-mark { + position: absolute; display: block; - float: left; - width: 30px; + top: -6px; + right: -6px; line-height: 100%; text-align: center; } @@ -615,7 +594,7 @@ a.action > img { padding-left: 6px; } -#fileList .action.action-favorite.permanent { +#fileList .favorite-mark.permanent { opacity: 1; } @@ -659,9 +638,6 @@ table tr.summary td { .summary .info { margin-left: 40px; } -.has-favorites .summary .info { - margin-left: 90px; -} table.dragshadow { width:auto; @@ -714,12 +690,24 @@ table.dragshadow td.size { #filestable .filename .action .icon, #filestable .selectedActions a .icon, +#filestable .filename .favorite-mark .icon, #controls .actions .button .icon { display: inline-block; vertical-align: middle; background-size: 16px 16px; } +#filestable .filename .favorite-mark { + // Override default icons to always hide the star icon and always show the + // starred icon even when hovered or focused. + & .icon-star { + background-image: none; + } + & .icon-starred { + background-image: url('../../../core/img/actions/starred.svg?v=1'); + } +} + #filestable .filename .action .icon.hidden, #filestable .selectedActions a .icon.hidden, #controls .actions .button .icon.hidden { diff --git a/apps/files/css/mobile.scss b/apps/files/css/mobile.scss index eefc92c816b..e7b75910fa9 100644 --- a/apps/files/css/mobile.scss +++ b/apps/files/css/mobile.scss @@ -24,10 +24,6 @@ table td.date { table td { padding: 0; } -/* and accordingly fix left margin of file list summary on mobile */ -.summary .info { - margin-left: 105px; -} /* remove shift for multiselect bar to account for missing navigation */ table.multiselect thead { diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 3da9b06b0d3..0f320c8b3c7 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -706,7 +706,7 @@ * @property {String} mime mime type * @property {int} permissions permissions * @property {(Function|String)} icon icon path to the icon or function that returns it (deprecated, use iconClass instead) - * @property {(Function|String)} iconClass class name of the icon (recommended for theming) + * @property {(String|OCA.Files.FileActions~iconClassFunction)} iconClass class name of the icon (recommended for theming) * @property {OCA.Files.FileActions~renderActionFunction} [render] optional rendering function * @property {OCA.Files.FileActions~actionHandler} actionHandler action handler function */ @@ -746,6 +746,17 @@ */ /** + * Icon class function for actions. + * The function returns the icon class of the action using + * the given context information. + * + * @callback OCA.Files.FileActions~iconClassFunction + * @param {String} fileName name of the file on which the action must be performed + * @param {OCA.Files.FileActionContext} context action context + * @return {String} icon class + */ + + /** * Action handler function for file actions * * @callback OCA.Files.FileActions~actionHandler diff --git a/apps/files/js/fileactionsmenu.js b/apps/files/js/fileactionsmenu.js index 45d2bd83049..b8022f13734 100644 --- a/apps/files/js/fileactionsmenu.js +++ b/apps/files/js/fileactionsmenu.js @@ -115,6 +115,11 @@ item = _.extend({}, item); item.displayName = item.displayName(self._context); } + if (_.isFunction(item.iconClass)) { + var fileName = self._context.$file.attr('data-file'); + item = _.extend({}, item); + item.iconClass = item.iconClass(fileName, self._context); + } return item; }); items = items.sort(function(actionA, actionB) { diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index cc23ac73979..0d45c29b25a 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -332,7 +332,7 @@ this.$fileList.on('click','td.filename>a.name, td.filesize, td.date', _.bind(this._onClickFile, this)); - this.$fileList.on('change', 'td.filename>.selectCheckBox', _.bind(this._onClickFileCheckbox, this)); + this.$fileList.on('change', 'td.selection>.selectCheckBox', _.bind(this._onClickFileCheckbox, this)); 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)); @@ -593,7 +593,7 @@ * @param {bool} state true to select, false to deselect */ _selectFileEl: function($tr, state, showDetailsView) { - var $checkbox = $tr.find('td.filename>.selectCheckBox'); + var $checkbox = $tr.find('td.selection>.selectCheckBox'); var oldData = !!this._selectedFiles[$tr.data('id')]; var data; $checkbox.prop('checked', state); @@ -649,7 +649,7 @@ else { this._lastChecked = $tr; } - var $checkbox = $tr.find('td.filename>.selectCheckBox'); + var $checkbox = $tr.find('td.selection>.selectCheckBox'); this._selectFileEl($tr, !$checkbox.prop('checked')); this.updateSelectionSummary(); } else { @@ -704,7 +704,7 @@ */ _onClickSelectAll: function(e) { var checked = $(e.target).prop('checked'); - this.$fileList.find('td.filename>.selectCheckBox').prop('checked', checked) + this.$fileList.find('td.selection>.selectCheckBox').prop('checked', checked) .closest('tr').toggleClass('selected', checked); this._selectedFiles = {}; this._selectionSummary.clear(); @@ -1063,6 +1063,13 @@ this.$fileList.empty(); + if (this._allowSelection) { + // The results table, which has no selection column, checks + // whether the main table has a selection column or not in order + // to align its contents with those of the main table. + this.$el.addClass('has-selection'); + } + // clear "Select all" checkbox this.$el.find('.select-all').prop('checked', false); @@ -1192,6 +1199,20 @@ path = this.getCurrentDirectory(); } + // selection td + if (this._allowSelection) { + td = $('<td class="selection"></td>'); + + td.append( + '<input id="select-' + this.id + '-' + fileData.id + + '" type="checkbox" class="selectCheckBox checkbox"/><label for="select-' + this.id + '-' + fileData.id + '">' + + '<span class="hidden-visually">' + t('files', 'Select') + '</span>' + + '</label>' + ); + + tr.append(td); + } + // filename td td = $('<td class="filename"></td>'); @@ -1203,22 +1224,13 @@ else { linkUrl = this.getDownloadUrl(name, path, type === 'dir'); } - if (this._allowSelection) { - td.append( - '<input id="select-' + this.id + '-' + fileData.id + - '" type="checkbox" class="selectCheckBox checkbox"/><label for="select-' + this.id + '-' + fileData.id + '">' + - '<div class="thumbnail" style="background-image:url(' + icon + '); background-size: 32px;"></div>' + - '<span class="hidden-visually">' + t('files', 'Select') + '</span>' + - '</label>' - ); - } else { - td.append('<div class="thumbnail" style="background-image:url(' + icon + '); background-size: 32px;"></div>'); - } var linkElem = $('<a></a>').attr({ "class": "name", "href": linkUrl }); + linkElem.append('<div class="thumbnail-wrapper"><div class="thumbnail" style="background-image:url(' + icon + ');"></div></div>'); + // from here work on the display name name = fileData.displayName || name; @@ -2614,6 +2626,13 @@ */ _createSummary: function() { var $tr = $('<tr class="summary"></tr>'); + + if (this._allowSelection) { + // Dummy column for selection, as all rows must have the same + // number of columns. + $tr.append('<td></td>'); + } + this.$el.find('tfoot').append($tr); return new OCA.Files.FileSummary($tr, {config: this._filesConfig}); diff --git a/apps/files/js/tagsplugin.js b/apps/files/js/tagsplugin.js index 9bd20be4bf8..2286477750c 100644 --- a/apps/files/js/tagsplugin.js +++ b/apps/files/js/tagsplugin.js @@ -17,12 +17,12 @@ PROPERTY_FAVORITE: '{' + OC.Files.Client.NS_OWNCLOUD + '}favorite' }); - var TEMPLATE_FAVORITE_ACTION = - '<a href="#" ' + - 'class="action action-favorite {{#isFavorite}}permanent{{/isFavorite}}">' + + var TEMPLATE_FAVORITE_MARK = + '<div ' + + 'class="favorite-mark {{#isFavorite}}permanent{{/isFavorite}}">' + '<span class="icon {{iconClass}}" />' + '<span class="hidden-visually">{{altText}}</span>' + - '</a>'; + '</div>'; /** * Returns the icon class for the matching state @@ -42,24 +42,24 @@ */ function renderStar(state) { if (!this._template) { - this._template = Handlebars.compile(TEMPLATE_FAVORITE_ACTION); + this._template = Handlebars.compile(TEMPLATE_FAVORITE_MARK); } return this._template({ isFavorite: state, - altText: state ? t('files', 'Favorited') : t('files', 'Favorite'), + altText: state ? t('files', 'Favorited') : t('files', 'Not favorited'), iconClass: getStarIconClass(state) }); } /** - * Toggle star icon on action element + * Toggle star icon on favorite mark element * - * @param {Object} action element + * @param {Object} $favoriteMarkEl favorite mark element * @param {boolean} state true if starred, false otherwise */ - function toggleStar($actionEl, state) { - $actionEl.removeClass('icon-star icon-starred').addClass(getStarIconClass(state)); - $actionEl.toggleClass('permanent', state); + function toggleStar($favoriteMarkEl, state) { + $favoriteMarkEl.removeClass('icon-star icon-starred').addClass(getStarIconClass(state)); + $favoriteMarkEl.toggleClass('permanent', state); } OCA.Files = OCA.Files || {}; @@ -67,8 +67,9 @@ /** * @namespace OCA.Files.TagsPlugin * - * Extends the file actions and file list to include a favorite action icon - * and addition "data-tags" and "data-favorite" attributes. + * Extends the file actions and file list to include a favorite mark icon + * and a favorite action in the file actions menu; it also adds "data-tags" + * and "data-favorite" attributes to file elements. */ OCA.Files.TagsPlugin = { name: 'Tags', @@ -84,22 +85,38 @@ _extendFileActions: function(fileActions) { var self = this; - // register "star" action + fileActions.registerAction({ name: 'Favorite', - displayName: t('files', 'Favorite'), + displayName: function(context) { + var $file = context.$file; + var isFavorite = $file.data('favorite') === true; + + if (isFavorite) { + return t('files', 'Remove from favorites'); + } + + // As it is currently not possible to provide a context for + // the i18n strings "Add to favorites" was used instead of + // "Favorite" to remove the ambiguity between verb and noun + // when it is translated. + return t('files', 'Add to favorites'); + }, mime: 'all', + order: -23, permissions: OC.PERMISSION_READ, - type: OCA.Files.FileActions.TYPE_INLINE, - render: function(actionSpec, isDefault, context) { + iconClass: function(fileName, context) { var $file = context.$file; var isFavorite = $file.data('favorite') === true; - var $icon = $(renderStar(isFavorite)); - $file.find('td:first>.favorite').replaceWith($icon); - return $icon; + + if (isFavorite) { + return 'icon-starred'; + } + + return 'icon-star'; }, actionHandler: function(fileName, context) { - var $actionEl = context.$file.find('.action-favorite'); + var $favoriteMarkEl = context.$file.find('.favorite-mark'); var $file = context.$file; var fileInfo = context.fileList.files[$file.index()]; var dir = context.dir || context.fileList.getCurrentDirectory(); @@ -118,14 +135,14 @@ } // pre-toggle the star - toggleStar($actionEl, !isFavorite); + toggleStar($favoriteMarkEl, !isFavorite); context.fileInfoModel.trigger('busy', context.fileInfoModel, true); self.applyFileTags( dir + '/' + fileName, tags, - $actionEl, + $favoriteMarkEl, isFavorite ).then(function(result) { context.fileInfoModel.trigger('busy', context.fileInfoModel, false); @@ -145,17 +162,19 @@ _extendFileList: function(fileList) { // extend row prototype - fileList.$el.addClass('has-favorites'); var oldCreateRow = fileList._createRow; fileList._createRow = function(fileData) { var $tr = oldCreateRow.apply(this, arguments); + var isFavorite = false; if (fileData.tags) { $tr.attr('data-tags', fileData.tags.join('|')); if (fileData.tags.indexOf(OC.TAG_FAVORITE) >= 0) { $tr.attr('data-favorite', true); + isFavorite = true; } } - $tr.find('td:first').prepend('<div class="favorite"></div>'); + var $icon = $(renderStar(isFavorite)); + $tr.find('td.filename .thumbnail').append($icon); return $tr; }; var oldElementToFile = fileList.elementToFile; @@ -215,10 +234,10 @@ * * @param {String} fileName path to the file or folder to tag * @param {Array.<String>} tagNames array of tag names - * @param {Object} $actionEl element + * @param {Object} $favoriteMarkEl favorite mark element * @param {boolean} isFavorite Was the item favorited before */ - applyFileTags: function(fileName, tagNames, $actionEl, isFavorite) { + applyFileTags: function(fileName, tagNames, $favoriteMarkEl, isFavorite) { var encodedPath = OC.encodePath(fileName); while (encodedPath[0] === '/') { encodedPath = encodedPath.substr(1); @@ -238,7 +257,7 @@ message = ': ' + response.responseJSON.message; } OC.Notification.show(t('files', 'An error occurred while trying to update the tags' + message), {type: 'error'}); - toggleStar($actionEl, isFavorite); + toggleStar($favoriteMarkEl, isFavorite); }); } }; diff --git a/apps/files/templates/list.php b/apps/files/templates/list.php index 761a67be6a2..f980081336f 100644 --- a/apps/files/templates/list.php +++ b/apps/files/templates/list.php @@ -41,12 +41,14 @@ <table id="filestable" data-allow-public-upload="<?php p($_['publicUploadEnabled'])?>" data-preview-x="32" data-preview-y="32"> <thead> <tr> + <th id="headerSelection" class="hidden column-selection"> + <input type="checkbox" id="select_all_files" class="select-all checkbox"/> + <label for="select_all_files"> + <span class="hidden-visually"><?php p($l->t('Select all'))?></span> + </label> + </th> <th id='headerName' class="hidden column-name"> <div id="headerName-container"> - <input type="checkbox" id="select_all_files" class="select-all checkbox"/> - <label for="select_all_files"> - <span class="hidden-visually"><?php p($l->t('Select all'))?></span> - </label> <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"> diff --git a/apps/files/tests/js/fileactionsmenuSpec.js b/apps/files/tests/js/fileactionsmenuSpec.js index 3028db2b3ac..926516b3043 100644 --- a/apps/files/tests/js/fileactionsmenuSpec.js +++ b/apps/files/tests/js/fileactionsmenuSpec.js @@ -205,6 +205,34 @@ describe('OCA.Files.FileActionsMenu tests', function() { expect(displayNameStub.calledWith(menuContext)).toEqual(true); expect(menu.$el.find('a[data-action=Something]').text()).toEqual('Test'); }); + it('uses plain iconClass', function() { + fileActions.registerAction({ + name: 'Something', + mime: 'text/plain', + permissions: OC.PERMISSION_ALL, + iconClass: 'test' + }); + + menu.render(); + + expect(menu.$el.find('a[data-action=Something]').children('span.icon').hasClass('test')).toEqual(true); + }); + it('calls iconClass function', function() { + var iconClassStub = sinon.stub().returns('test'); + + fileActions.registerAction({ + name: 'Something', + mime: 'text/plain', + permissions: OC.PERMISSION_ALL, + iconClass: iconClassStub + }); + + menu.render(); + + expect(iconClassStub.calledOnce).toEqual(true); + expect(iconClassStub.calledWith(menuContext.$file.attr('data-file'), menuContext)).toEqual(true); + expect(menu.$el.find('a[data-action=Something]').children('span.icon').hasClass('test')).toEqual(true); + }); }); describe('action handler', function() { diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 836a5e5ce71..1f8d38c59ce 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -712,8 +712,14 @@ describe('OCA.Files.FileList tests', function() { fileList.add(testFiles[i], {silent: true}); } + $tr = fileList.findFileEl('One.txt'); + expect($tr.find('a.name').css('display')).not.toEqual('none'); + // trigger rename prompt fileList.rename('One.txt'); + + expect($tr.find('a.name').css('display')).toEqual('none'); + $input = fileList.$fileList.find('input.filename'); $input.val('Two.jpg'); @@ -735,12 +741,12 @@ describe('OCA.Files.FileList tests', function() { $tr = fileList.findFileEl('One.txt'); expect($tr.length).toEqual(1); expect($tr.find('a .nametext').text().trim()).toEqual('One.txt'); - expect($tr.find('a.name').is(':visible')).toEqual(true); + expect($tr.find('a.name').css('display')).not.toEqual('none'); $tr = fileList.findFileEl('Two.jpg'); expect($tr.length).toEqual(1); expect($tr.find('a .nametext').text().trim()).toEqual('Two.jpg'); - expect($tr.find('a.name').is(':visible')).toEqual(true); + expect($tr.find('a.name').css('display')).not.toEqual('none'); // input and form are gone expect(fileList.$fileList.find('input.filename').length).toEqual(0); @@ -750,7 +756,7 @@ describe('OCA.Files.FileList tests', function() { doRename(); expect(fileList.findFileEl('Tu_after_three.txt').find('.thumbnail').parent().attr('class')) - .toEqual('icon-loading-small'); + .toContain('icon-loading-small'); deferredRename.reject(409); @@ -838,7 +844,7 @@ describe('OCA.Files.FileList tests', function() { fileList.move('One.txt', '/somedir'); expect(fileList.findFileEl('One.txt').find('.thumbnail').parent().attr('class')) - .toEqual('icon-loading-small'); + .toContain('icon-loading-small'); expect(moveStub.calledOnce).toEqual(true); @@ -935,7 +941,7 @@ describe('OCA.Files.FileList tests', function() { fileList.copy('One.txt', '/somedir'); expect(fileList.findFileEl('One.txt').find('.thumbnail').parent().attr('class')) - .toEqual('icon-loading-small'); + .toContain('icon-loading-small'); expect(copyStub.calledOnce).toEqual(true); @@ -1741,7 +1747,7 @@ describe('OCA.Files.FileList tests', function() { it('Selects a file when clicking its checkbox', function() { var $tr = fileList.findFileEl('One.txt'); expect($tr.find('input:checkbox').prop('checked')).toEqual(false); - $tr.find('td.filename input:checkbox').click(); + $tr.find('td.selection input:checkbox').click(); expect($tr.find('input:checkbox').prop('checked')).toEqual(true); }); @@ -1779,7 +1785,7 @@ describe('OCA.Files.FileList tests', function() { var $tr = fileList.findFileEl('One.txt'); var $tr2 = fileList.findFileEl('Three.pdf'); var e; - $tr.find('td.filename input:checkbox').click(); + $tr.find('td.selection input:checkbox').click(); e = new $.Event('click'); e.shiftKey = true; $tr2.find('td.filename .name').trigger(e); @@ -1797,7 +1803,7 @@ describe('OCA.Files.FileList tests', function() { var $tr = fileList.findFileEl('One.txt'); var $tr2 = fileList.findFileEl('Three.pdf'); var e; - $tr2.find('td.filename input:checkbox').click(); + $tr2.find('td.selection input:checkbox').click(); e = new $.Event('click'); e.shiftKey = true; $tr.find('td.filename .name').trigger(e); @@ -1813,13 +1819,13 @@ describe('OCA.Files.FileList tests', function() { }); it('Selecting all files will automatically check "select all" checkbox', function() { expect($('.select-all').prop('checked')).toEqual(false); - $('#fileList tr td.filename input:checkbox').click(); + $('#fileList tr td.selection input:checkbox').click(); expect($('.select-all').prop('checked')).toEqual(true); }); it('Selecting all files on the first visible page will not automatically check "select all" checkbox', function() { fileList.setFiles(generateFiles(0, 41)); expect($('.select-all').prop('checked')).toEqual(false); - $('#fileList tr td.filename input:checkbox').click(); + $('#fileList tr td.selection input:checkbox').click(); expect($('.select-all').prop('checked')).toEqual(false); }); it('Selecting all files also selects hidden files when invisible', function() { @@ -1831,7 +1837,7 @@ describe('OCA.Files.FileList tests', function() { size: 150 })); $('.select-all').click(); - expect($tr.find('td.filename input:checkbox').prop('checked')).toEqual(true); + expect($tr.find('td.selection input:checkbox').prop('checked')).toEqual(true); expect(_.pluck(fileList.getSelectedFiles(), 'name')).toContain('.hidden'); }); it('Clicking "select all" will select/deselect all files', function() { @@ -3150,7 +3156,7 @@ describe('OCA.Files.FileList tests', function() { fileList.showFileBusyState('Two.jpg', true); expect($tr.hasClass('busy')).toEqual(true); expect($tr.find('.thumbnail').parent().attr('class')) - .toEqual('icon-loading-small'); + .toContain('icon-loading-small'); fileList.showFileBusyState('Two.jpg', false); diff --git a/apps/files/tests/js/tagspluginspec.js b/apps/files/tests/js/tagspluginspec.js index a4efc08aa53..363a8bb0e19 100644 --- a/apps/files/tests/js/tagspluginspec.js +++ b/apps/files/tests/js/tagspluginspec.js @@ -49,39 +49,39 @@ describe('OCA.Files.TagsPlugin tests', function() { describe('Favorites icon', function() { it('renders favorite icon and extra data', function() { - var $action, $tr; + var $favoriteMark, $tr; fileList.setFiles(testFiles); $tr = fileList.$el.find('tbody tr:first'); - $action = $tr.find('.action-favorite'); - expect($action.length).toEqual(1); - expect($action.hasClass('permanent')).toEqual(false); + $favoriteMark = $tr.find('.favorite-mark'); + expect($favoriteMark.length).toEqual(1); + expect($favoriteMark.hasClass('permanent')).toEqual(false); expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2']); expect($tr.attr('data-favorite')).not.toBeDefined(); }); it('renders permanent favorite icon and extra data', function() { - var $action, $tr; + var $favoriteMark, $tr; testFiles[0].tags.push(OC.TAG_FAVORITE); fileList.setFiles(testFiles); $tr = fileList.$el.find('tbody tr:first'); - $action = $tr.find('.action-favorite'); - expect($action.length).toEqual(1); - expect($action.hasClass('permanent')).toEqual(true); + $favoriteMark = $tr.find('.favorite-mark'); + expect($favoriteMark.length).toEqual(1); + expect($favoriteMark.hasClass('permanent')).toEqual(true); expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', OC.TAG_FAVORITE]); expect($tr.attr('data-favorite')).toEqual('true'); }); - it('adds has-favorites class on table', function() { - expect(fileList.$el.hasClass('has-favorites')).toEqual(true); - }); }); describe('Applying tags', function() { - it('sends request to server and updates icon', function() { + it('through FileActionsMenu sends request to server and updates icon', function() { var request; fileList.setFiles(testFiles); var $tr = fileList.findFileEl('One.txt'); - var $action = $tr.find('.action-favorite'); - $action.click(); + var $favoriteMark = $tr.find('.favorite-mark'); + var $showMenuAction = $tr.find('.action-menu'); + $showMenuAction.click(); + var $favoriteActionInMenu = $tr.find('.fileActionsMenu .action-favorite'); + $favoriteActionInMenu.click(); expect(fakeServer.requests.length).toEqual(1); request = fakeServer.requests[0]; @@ -94,15 +94,21 @@ describe('OCA.Files.TagsPlugin tests', function() { // re-read the element as it was re-inserted $tr = fileList.findFileEl('One.txt'); - $action = $tr.find('.action-favorite'); + $favoriteMark = $tr.find('.favorite-mark'); + $showMenuAction = $tr.find('.action-menu'); expect($tr.attr('data-favorite')).toEqual('true'); expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE]); expect(fileList.files[0].tags).toEqual(['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE]); - expect($action.find('.icon').hasClass('icon-star')).toEqual(false); - expect($action.find('.icon').hasClass('icon-starred')).toEqual(true); + expect($favoriteMark.find('.icon').hasClass('icon-star')).toEqual(false); + expect($favoriteMark.find('.icon').hasClass('icon-starred')).toEqual(true); - $action.click(); + // show again the menu and get the new action, as the menu was + // closed and removed (and with it, the previous action) when that + // action was clicked + $showMenuAction.click(); + $favoriteActionInMenu = $tr.find('.fileActionsMenu .action-favorite'); + $favoriteActionInMenu.click(); expect(fakeServer.requests.length).toEqual(2); request = fakeServer.requests[1]; @@ -115,13 +121,13 @@ describe('OCA.Files.TagsPlugin tests', function() { // re-read the element as it was re-inserted $tr = fileList.findFileEl('One.txt'); - $action = $tr.find('.action-favorite'); + $favoriteMark = $tr.find('.favorite-mark'); expect($tr.attr('data-favorite')).toBeFalsy(); expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', 'tag3']); expect(fileList.files[0].tags).toEqual(['tag1', 'tag2', 'tag3']); - expect($action.find('.icon').hasClass('icon-star')).toEqual(true); - expect($action.find('.icon').hasClass('icon-starred')).toEqual(false); + expect($favoriteMark.find('.icon').hasClass('icon-star')).toEqual(true); + expect($favoriteMark.find('.icon').hasClass('icon-starred')).toEqual(false); }); }); describe('elementToFile', function() { diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php index c3f0304d408..b3ebca2867b 100644 --- a/apps/files_trashbin/templates/index.php +++ b/apps/files_trashbin/templates/index.php @@ -21,12 +21,14 @@ <table id="filestable"> <thead> <tr> + <th id="headerSelection" class="hidden column-selection"> + <input type="checkbox" id="select_all_trash" class="select-all checkbox"/> + <label for="select_all_trash"> + <span class="hidden-visually"><?php p($l->t('Select all'))?></span> + </label> + </th> <th id='headerName' class="hidden column-name"> <div id="headerName-container"> - <input type="checkbox" id="select_all_trash" class="select-all checkbox"/> - <label for="select_all_trash"> - <span class="hidden-visually"><?php p($l->t('Select all'))?></span> - </label> <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"> |