diff options
Diffstat (limited to 'apps/files/js/filelist.js')
-rw-r--r-- | apps/files/js/filelist.js | 572 |
1 files changed, 324 insertions, 248 deletions
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index d1f68d98eab..2c97816df00 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -22,11 +22,12 @@ * * @param $el container element with existing markup for the #controls * and a table - * @param [options] map of options, see other parameters - * @param [options.scrollContainer] scrollable container, defaults to $(window) - * @param [options.dragOptions] drag options, disabled by default - * @param [options.folderDropOptions] folder drop options, disabled by default - * @param [options.detailsViewEnabled=true] whether to enable details view + * @param {Object} [options] map of options, see other parameters + * @param {Object} [options.scrollContainer] scrollable container, defaults to $(window) + * @param {Object} [options.dragOptions] drag options, disabled by default + * @param {Object} [options.folderDropOptions] folder drop options, disabled by default + * @param {boolean} [options.detailsViewEnabled=true] whether to enable details view + * @param {OC.Files.Client} [options.filesClient] files client to use */ var FileList = function($el, options) { this.initialize($el, options); @@ -74,6 +75,13 @@ _detailsView: null, /** + * Files client instance + * + * @type OC.Files.Client + */ + filesClient: null, + + /** * Whether the file list was initialized already. * @type boolean */ @@ -92,11 +100,18 @@ * Array of files in the current folder. * The entries are of file data. * - * @type Array.<Object> + * @type Array.<OC.Files.FileInfo> */ files: [], /** + * Current directory entry + * + * @type OC.Files.FileInfo + */ + dirInfo: null, + + /** * File actions handler, defaults to OCA.Files.FileActions * @type OCA.Files.FileActions */ @@ -149,7 +164,7 @@ * When false, clicking on a table header will call reload(). * When true, clicking on a table header will simply resort the list. */ - _clientSideSort: false, + _clientSideSort: true, /** * Current directory @@ -170,6 +185,7 @@ * @param options.dragOptions drag options, disabled by default * @param options.folderDropOptions folder drop options, disabled by default * @param options.scrollTo name of file to scroll to after the first load + * @param {OC.Files.Client} [options.filesClient] files API client * @private */ initialize: function($el, options) { @@ -185,6 +201,12 @@ if (options.folderDropOptions) { this._folderDropOptions = options.folderDropOptions; } + if (options.filesClient) { + this.filesClient = options.filesClient; + } else { + // default client if not specified + this.filesClient = OC.Files.getClient(); + } this.$el = $el; if (options.id) { @@ -209,6 +231,8 @@ this.files = []; this._selectedFiles = {}; this._selectionSummary = new OCA.Files.FileSummary(); + // dummy root dir info + this.dirInfo = new OC.Files.FileInfo({}); this.fileSummary = this._createSummary(); @@ -359,7 +383,7 @@ var highlightState = $tr.hasClass('highlighted'); $tr = self.updateRow( $tr, - _.extend({isPreviewAvailable: true}, model.toJSON()), + model.toJSON(), {updateSummary: true, silent: false, animate: true} ); $tr.toggleClass('highlighted', highlightState); @@ -618,7 +642,7 @@ }; OCA.Files.FileActions.updateFileActionSpinner(downloadFileaction, true); - OCA.Files.Files.handleDownload(this.getDownloadUrl(files, dir), disableLoadingState); + OCA.Files.Files.handleDownload(this.getDownloadUrl(files, dir, true), disableLoadingState); return false; }, @@ -894,16 +918,39 @@ self.$el.closest('#app-content').trigger(jQuery.Event('apprendered')); }); }, + + /** + * Returns the icon URL matching the given file info + * + * @param {OC.Files.FileInfo} fileInfo file info + * + * @return {string} icon URL + */ + _getIconUrl: function(fileInfo) { + var mimeType = fileInfo.mimetype || 'application/octet-stream'; + if (mimeType === 'httpd/unix-directory') { + // use default folder icon + if (fileInfo.mountType === 'shared' || fileInfo.mountType === 'shared-root') { + return OC.MimeType.getIconUrl('dir-shared'); + } else if (fileInfo.mountType === 'external-root') { + return OC.MimeType.getIconUrl('dir-external'); + } + return OC.MimeType.getIconUrl('dir'); + } + return OC.MimeType.getIconUrl(mimeType); + }, + /** * Creates a new table row element using the given file data. - * @param {OCA.Files.FileInfo} fileData file info attributes + * @param {OC.Files.FileInfo} fileData file info attributes * @param options map of attributes * @return new tr element (not appended to the table) */ _createRow: function(fileData, options) { var td, simpleSize, basename, extension, sizeColor, - icon = OC.MimeType.getIconUrl(fileData.mimetype), + icon = fileData.icon || this._getIconUrl(fileData), name = fileData.name, + // TODO: get rid of type, only use mime type type = fileData.type || 'file', mtime = parseInt(fileData.mtime, 10), mime = fileData.mimetype, @@ -943,6 +990,14 @@ } if (fileData.mountType) { + // FIXME: HACK: detect shared-root + if (fileData.mountType === 'shared' && this.dirInfo.mountType !== 'shared') { + // if parent folder isn't share, assume the displayed folder is a share root + fileData.mountType = 'shared-root'; + } else if (fileData.mountType === 'external' && this.dirInfo.mountType !== 'external') { + // if parent folder isn't external, assume the displayed folder is the external storage root + fileData.mountType = 'external-root'; + } tr.attr('data-mounttype', fileData.mountType); } @@ -953,24 +1008,16 @@ path = this.getCurrentDirectory(); } - if (type === 'dir') { - // use default folder icon - icon = icon || OC.imagePath('core', 'filetypes/folder'); - } - else { - icon = icon || OC.imagePath('core', 'filetypes/file'); - } - // filename td td = $('<td class="filename"></td>'); // linkUrl - if (type === 'dir') { + if (mime === 'httpd/unix-directory') { linkUrl = this.linkTo(path + '/' + name); } else { - linkUrl = this.getDownloadUrl(name, path); + linkUrl = this.getDownloadUrl(name, path, type === 'dir'); } if (this._allowSelection) { td.append( @@ -996,7 +1043,7 @@ basename = ''; extension = name; // split extension from filename for non dirs - } else if (type !== 'dir' && name.indexOf('.') !== -1) { + } else if (mime !== 'httpd/unix-directory' && name.indexOf('.') !== -1) { basename = name.substr(0, name.lastIndexOf('.')); extension = name.substr(name.lastIndexOf('.')); } else { @@ -1018,7 +1065,7 @@ nameSpan.tooltip({placement: 'right'}); } // dirs can show the number of uploaded files - if (type === 'dir') { + if (mime !== 'httpd/unix-directory') { linkElem.append($('<span></span>').attr({ 'class': 'uploadtext', 'currentUploads': 0 @@ -1074,7 +1121,7 @@ * Adds an entry to the files array and also into the DOM * in a sorted manner. * - * @param {OCA.Files.FileInfo} fileData map of file attributes + * @param {OC.Files.FileInfo} fileData map of file attributes * @param {Object} [options] map of attributes * @param {boolean} [options.updateSummary] true to update the summary * after adding (default), false otherwise. Defaults to true. @@ -1147,7 +1194,7 @@ * Creates a new row element based on the given attributes * and returns it. * - * @param {OCA.Files.FileInfo} fileData map of file attributes + * @param {OC.Files.FileInfo} fileData map of file attributes * @param {Object} [options] map of attributes * @param {int} [options.index] index at which to insert the element * @param {boolean} [options.updateSummary] true to update the summary @@ -1182,7 +1229,7 @@ filenameTd.draggable(this._dragOptions); } // allow dropping on folders - if (this._folderDropOptions && fileData.type === 'dir') { + if (this._folderDropOptions && mime === 'httpd/unix-directory') { filenameTd.droppable(this._folderDropOptions); } @@ -1193,7 +1240,7 @@ // display actions this.fileActions.display(filenameTd, !options.silent, this); - if (fileData.isPreviewAvailable && mime !== 'httpd/unix-directory') { + if (mime !== 'httpd/unix-directory') { var iconDiv = filenameTd.find('.thumbnail'); // lazy load / newly inserted td ? // the typeof check ensures that the default value of animate is true @@ -1343,17 +1390,7 @@ this._currentFileModel = null; this.$el.find('.select-all').prop('checked', false); this.showMask(); - if (this._reloadCall) { - this._reloadCall.abort(); - } - this._reloadCall = $.ajax({ - url: this.getAjaxUrl('list'), - data: { - dir : this.getCurrentDirectory(), - sort: this._sort, - sortdirection: this._sortDirection - } - }); + this._reloadCall = this.filesClient.getFolderContents(this.getCurrentDirectory(), {includeParent: true}); if (this._detailsView) { // close sidebar this._updateDetailsView(null); @@ -1361,24 +1398,19 @@ var callBack = this.reloadCallback.bind(this); return this._reloadCall.then(callBack, callBack); }, - reloadCallback: function(result) { + reloadCallback: function(status, result) { delete this._reloadCall; this.hideMask(); - if (!result || result.status === 'error') { - // if the error is not related to folder we're trying to load, reload the page to handle logout etc - if (result.data.error === 'authentication_error' || - result.data.error === 'token_expired' || - result.data.error === 'application_not_enabled' - ) { - OC.redirect(OC.generateUrl('apps/files')); - } - OC.Notification.showTemporary(result.data.message); + if (status === 401) { + // TODO: append current URL to be able to get back after logging in again + OC.redirect(OC.generateUrl('apps/files')); + OC.Notification.show(result); return false; } // Firewall Blocked request? - if (result.status === 403) { + if (status === 403) { // Go home this.changeDirectory('/'); OC.Notification.showTemporary(t('files', 'This operation is forbidden')); @@ -1386,32 +1418,49 @@ } // Did share service die or something else fail? - if (result.status === 500) { + if (status === 500) { // Go home this.changeDirectory('/'); - OC.Notification.showTemporary(t('files', 'This directory is unavailable, please check the logs or contact the administrator')); + OC.Notification.showTemporary( + t('files', 'This directory is unavailable, please check the logs or contact the administrator') + ); + return false; + } + + if (status === 503) { + // Go home + if (this.getCurrentDirectory() !== '/') { + this.changeDirectory('/'); + // TODO: read error message from exception + OC.Notification.showTemporary( + t('files', 'Storage not available') + ); + } return false; } - if (result.status === 404) { + if (status === 404) { // go back home this.changeDirectory('/'); return false; } // aborted ? - if (result.status === 0){ + if (status === 0){ return true; } - // TODO: should rather return upload file size through - // the files list ajax call + // TODO: parse remaining quota from PROPFIND response this.updateStorageStatistics(true); - if (result.data.permissions) { - this.setDirectoryPermissions(result.data.permissions); + // first entry is the root + this.dirInfo = result.shift(); + + if (this.dirInfo.permissions) { + this.setDirectoryPermissions(this.dirInfo.permissions); } - this.setFiles(result.data.files); + result.sort(this._sortComparator); + this.setFiles(result); return true; }, @@ -1419,12 +1468,15 @@ OCA.Files.Files.updateStorageStatistics(this.getCurrentDirectory(), force); }, + /** + * @deprecated do not use nor override + */ getAjaxUrl: function(action, params) { return OCA.Files.Files.getAjaxUrl(action, params); }, - getDownloadUrl: function(files, dir) { - return OCA.Files.Files.getDownloadUrl(files, dir || this.getCurrentDirectory()); + getDownloadUrl: function(files, dir, isDir) { + return OCA.Files.Files.getDownloadUrl(files, dir || this.getCurrentDirectory(), isDir); }, /** @@ -1489,8 +1541,6 @@ if (etag){ // use etag as cache buster urlSpec.c = etag; - } else { - console.warn('OCA.Files.FileList.lazyLoadPreview(): missing etag argument'); } previewURL = self.generatePreviewUrl(urlSpec); @@ -1514,6 +1564,9 @@ img.src = previewURL; }, + /** + * @deprecated + */ setDirectoryPermissions: function(permissions) { var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; this.$el.find('#permissions').val(permissions); @@ -1610,7 +1663,7 @@ * fileData should be inserted, considering the current * sorting * - * @param {OCA.Files.FileInfo} fileData file info + * @param {OC.Files.FileInfo} fileData file info */ _findInsertionIndex: function(fileData) { var index = 0; @@ -1628,6 +1681,9 @@ move: function(fileNames, targetPath) { var self = this; var dir = this.getCurrentDirectory(); + if (dir.charAt(dir.length - 1) !== '/') { + dir += '/'; + } var target = OC.basename(targetPath); if (!_.isArray(fileNames)) { fileNames = [fileNames]; @@ -1635,46 +1691,42 @@ _.each(fileNames, function(fileName) { var $tr = self.findFileEl(fileName); self.showFileBusyState($tr, true); - // TODO: improve performance by sending all file names in a single call - $.post( - OC.filePath('files', 'ajax', 'move.php'), - { - dir: dir, - file: fileName, - target: targetPath - }, - function(result) { - if (result) { - if (result.status === 'success') { - // if still viewing the same directory - if (self.getCurrentDirectory() === dir) { - // recalculate folder size - var oldFile = self.findFileEl(target); - var newFile = self.findFileEl(fileName); - var oldSize = oldFile.data('size'); - var newSize = oldSize + newFile.data('size'); - oldFile.data('size', newSize); - oldFile.find('td.filesize').text(OC.Util.humanFileSize(newSize)); - - // TODO: also update entry in FileList.files - - self.remove(fileName); - } - } else { - OC.Notification.hide(); - if (result.status === 'error' && result.data.message) { - OC.Notification.showTemporary(result.data.message); - } - else { - OC.Notification.showTemporary(t('files', 'Error moving file.')); - } - } + if (targetPath.charAt(targetPath.length - 1) !== '/') { + // make sure we move the files into the target dir, + // not overwrite it + targetPath = targetPath + '/'; + } + self.filesClient.move(dir + fileName, targetPath + fileName) + .done(function() { + // if still viewing the same directory + if (OC.joinPaths(self.getCurrentDirectory(), '/') === dir) { + // recalculate folder size + var oldFile = self.findFileEl(target); + var newFile = self.findFileEl(fileName); + var oldSize = oldFile.data('size'); + var newSize = oldSize + newFile.data('size'); + oldFile.data('size', newSize); + oldFile.find('td.filesize').text(OC.Util.humanFileSize(newSize)); + + // TODO: also update entry in FileList.files + self.remove(fileName); + } + }) + .fail(function(status) { + if (status === 412) { + // TODO: some day here we should invoke the conflict dialog + OC.Notification.showTemporary( + t('files', 'Could not move "{file}", target exists', {file: fileName}) + ); } else { - OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); + OC.Notification.showTemporary( + t('files', 'Could not move "{file}"', {file: fileName}) + ); } + }) + .always(function() { self.showFileBusyState($tr, false); - } - ); + }); }); }, @@ -1700,16 +1752,16 @@ * Triggers file rename input field for the given file name. * If the user enters a new name, the file will be renamed. * - * @param oldname file name of the file to rename + * @param oldName file name of the file to rename */ - rename: function(oldname) { + rename: function(oldName) { var self = this; var tr, td, input, form; - tr = this.findFileEl(oldname); + tr = this.findFileEl(oldName); var oldFileInfo = this.files[tr.index()]; tr.data('renaming',true); td = tr.children('td.filename'); - input = $('<input type="text" class="filename"/>').val(oldname); + input = $('<input type="text" class="filename"/>').val(oldName); form = $('<form></form>'); form.append(input); td.children('a.name').hide(); @@ -1724,11 +1776,11 @@ input.selectRange(0, len); var checkInput = function () { var filename = input.val(); - if (filename !== oldname) { + if (filename !== oldName) { // Files.isFileNameValid(filename) throws an exception itself OCA.Files.Files.isFileNameValid(filename); if (self.inList(filename)) { - throw t('files', '{new_name} already exists', {new_name: filename}); + throw t('files', '{newName} already exists', {newName: filename}); } } return true; @@ -1741,6 +1793,14 @@ td.children('a.name').show(); } + function updateInList(fileInfo) { + tr.remove(); + tr = self.add(fileInfo, {updateSummary: false, silent: true}); + self.$fileList.trigger($.Event('fileActionsReady', {fileList: self, $files: $(tr)})); + self._updateDetailsView(fileInfo.name); + } + + // TODO: too many nested blocks, move parts into functions form.submit(function(event) { event.stopPropagation(); event.preventDefault(); @@ -1753,7 +1813,7 @@ input.tooltip('hide'); form.remove(); - if (newName !== oldname) { + if (newName !== oldName) { checkInput(); // mark as loading (temp element) self.showFileBusyState(tr, true); @@ -1765,34 +1825,46 @@ td.find('a.name span.nametext').text(basename); td.children('a.name').show(); - $.ajax({ - url: OC.filePath('files','ajax','rename.php'), - data: { - dir : tr.attr('data-path') || self.getCurrentDirectory(), - newname: newName, - file: oldname - }, - success: function(result) { - var fileInfo; - if (!result || result.status === 'error') { - OC.dialogs.alert(result.data.message, t('files', 'Could not rename file')); - fileInfo = oldFileInfo; - if (result.data.code === 'sourcenotfound') { - self.remove(result.data.newname, {updateSummary: true}); - return; - } - } - else { - fileInfo = result.data; + var path = tr.attr('data-path') || self.getCurrentDirectory(); + self.filesClient.move(path + '/' + oldName, path + '/' + newName) + .done(function() { + var fileInfo = self.files.splice(tr.index(), 1)[0]; + fileInfo.name = newName; + updateInList(fileInfo); + }) + .fail(function(status) { + // TODO: 409 means current folder does not exist, redirect ? + if (status === 404) { + // source not found, so remove it from the list + OC.Notification.showTemporary( + t( + 'files', + 'Could not rename "{fileName}", it does not exist any more', + {fileName: oldName} + ) + ); + self.remove(newName, {updateSummary: true}); + return; + } else if (status === 412) { + // target exists + OC.Notification.showTemporary( + t( + 'files', + 'The name "{targetName}" is already used in the folder "{dir}". Please choose a different name.', + { + targetName: newName, + dir: self.getCurrentDirectory() + } + ) + ); + } else { + // restore the item to its previous state + OC.Notification.showTemporary( + t('files', 'Could not rename "{fileName}"', {fileName: oldName}) + ); } - // reinsert row - self.files.splice(tr.index(), 1); - tr.remove(); - tr = self.add(fileInfo, {updateSummary: false, silent: true}); - self.$fileList.trigger($.Event('fileActionsReady', {fileList: self, $files: $(tr)})); - self._updateDetailsView(fileInfo.name, false); - } - }); + updateInList(oldFileInfo); + }); } else { // add back the old file info when cancelled self.files.splice(tr.index(), 1); @@ -1849,32 +1921,44 @@ var promise = deferred.promise(); OCA.Files.Files.isFileNameValid(name); - name = this.getUniqueName(name); if (this.lastAction) { this.lastAction(); } - $.post( - OC.generateUrl('/apps/files/ajax/newfile.php'), - { - dir: this.getCurrentDirectory(), - filename: name - }, - function(result) { - if (result.status === 'success') { - self.add(result.data, {animate: true, scrollTo: true}); - deferred.resolve(result.status, result.data); + name = this.getUniqueName(name); + var targetPath = this.getCurrentDirectory() + '/' + name; + + self.filesClient.putFileContents( + targetPath, + '', + { + contentType: 'text/plain', + overwrite: true + } + ) + .done(function() { + // TODO: error handling / conflicts + self.filesClient.getFileInfo(targetPath) + .then(function(status, data) { + self.add(data, {animate: true, scrollTo: true}); + deferred.resolve(status, data); + }) + .fail(function(status) { + OC.Notification.showTemporary(t('files', 'Could not create file "{file}"', {file: name})); + deferred.reject(status); + }); + }) + .fail(function(status) { + if (status === 412) { + OC.Notification.showTemporary( + t('files', 'Could not create file "{file}" because it already exists', {file: name}) + ); } else { - if (result.data && result.data.message) { - OC.Notification.showTemporary(result.data.message); - } else { - OC.Notification.showTemporary(t('core', 'Could not create file')); - } - deferred.reject(result.status, result.data); + OC.Notification.showTemporary(t('files', 'Could not create file "{file}"', {file: name})); } - } - ); + deferred.reject(status); + }); return promise; }, @@ -1895,32 +1979,50 @@ var promise = deferred.promise(); OCA.Files.Files.isFileNameValid(name); - name = this.getUniqueName(name); if (this.lastAction) { this.lastAction(); } - $.post( - OC.generateUrl('/apps/files/ajax/newfolder.php'), - { - dir: this.getCurrentDirectory(), - foldername: name - }, - function(result) { - if (result.status === 'success') { - self.add(result.data, {animate: true, scrollTo: true}); - deferred.resolve(result.status, result.data); + name = this.getUniqueName(name); + var targetPath = this.getCurrentDirectory() + '/' + name; + + this.filesClient.createDirectory(targetPath) + .done(function(createStatus) { + self.filesClient.getFileInfo(targetPath) + .done(function(status, data) { + self.add(data, {animate: true, scrollTo: true}); + deferred.resolve(status, data); + }) + .fail(function() { + OC.Notification.showTemporary(t('files', 'Could not create folder "{dir}"', {dir: name})); + deferred.reject(createStatus); + }); + }) + .fail(function(createStatus) { + // method not allowed, folder might exist already + if (createStatus === 405) { + self.filesClient.getFileInfo(targetPath) + .done(function(status, data) { + // add it to the list, for completeness + self.add(data, {animate: true, scrollTo: true}); + OC.Notification.showTemporary( + t('files', 'Could not create folder "{dir}" because it already exists', {dir: name}) + ); + // still consider a failure + deferred.reject(createStatus, data); + }) + .fail(function() { + OC.Notification.showTemporary( + t('files', 'Could not create folder "{dir}"', {dir: name}) + ); + deferred.reject(status); + }); } else { - if (result.data && result.data.message) { - OC.Notification.showTemporary(result.data.message); - } else { - OC.Notification.showTemporary(t('core', 'Could not create folder')); - } - deferred.reject(result.status); + OC.Notification.showTemporary(t('files', 'Could not create folder "{dir}"', {dir: name})); + deferred.reject(createStatus); } - } - ); + }); return promise; }, @@ -1981,76 +2083,59 @@ */ do_delete:function(files, dir) { var self = this; - var params; if (files && files.substr) { files=[files]; } + if (!files) { + // delete all files in directory + files = _.pluck(this.files, 'name'); + } if (files) { this.showFileBusyState(files, true); - for (var i=0; i<files.length; i++) { - } } // Finish any existing actions if (this.lastAction) { this.lastAction(); } - params = { - dir: dir || this.getCurrentDirectory() - }; - if (files) { - params.files = JSON.stringify(files); + dir = dir || this.getCurrentDirectory(); + + function removeFromList(file) { + var fileEl = self.remove(file, {updateSummary: false}); + // FIXME: not sure why we need this after the + // element isn't even in the DOM any more + fileEl.find('.selectCheckBox').prop('checked', false); + fileEl.removeClass('selected'); + self.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')}); + // TODO: this info should be returned by the ajax call! + self.updateEmptyContent(); + self.fileSummary.update(); + self.updateSelectionSummary(); + // FIXME: don't repeat this, do it once all files are done + self.updateStorageStatistics(); } - else { - // no files passed, delete all in current dir - params.allfiles = true; - // show spinner for all files - this.showFileBusyState(this.$fileList.find('tr'), true); - } - - $.post(OC.filePath('files', 'ajax', 'delete.php'), - params, - function(result) { - if (result.status === 'success') { - if (params.allfiles) { - self.setFiles([]); - } - else { - $.each(files,function(index,file) { - var fileEl = self.remove(file, {updateSummary: false}); - // FIXME: not sure why we need this after the - // element isn't even in the DOM any more - fileEl.find('.selectCheckBox').prop('checked', false); - fileEl.removeClass('selected'); - self.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')}); - }); - } - // TODO: this info should be returned by the ajax call! - self.updateEmptyContent(); - self.fileSummary.update(); - self.updateSelectionSummary(); - self.updateStorageStatistics(); - // in case there was a "storage full" permanent notification - OC.Notification.hide(); + + _.each(files, function(file) { + self.filesClient.remove(dir + '/' + file) + .done(function() { + removeFromList(file); + }) + .fail(function(status) { + if (status === 404) { + // the file already did not exist, remove it from the list + removeFromList(file); } else { - if (result.status === 'error' && result.data.message) { - OC.Notification.showTemporary(result.data.message); - } - else { - OC.Notification.showTemporary(t('files', 'Error deleting file.')); - } - if (params.allfiles) { - // reload the page as we don't know what files were deleted - // and which ones remain - self.reload(); - } - else { - $.each(files,function(index,file) { - self.showFileBusyState(file, false); - }); - } + // only reset the spinner for that one file + OC.Notification.showTemporary( + t('files', 'Error deleting file "{fileName}".', {fileName: file}), + {timeout: 10} + ); + var deleteAction = self.findFileEl(file).find('.action.delete'); + deleteAction.removeClass('icon-loading-small').addClass('icon-delete'); + self.showFileBusyState(files, false); } }); + }); }, /** * Creates the file summary section @@ -2659,8 +2744,8 @@ * Compares two file infos by name, making directories appear * first. * - * @param {OCA.Files.FileInfo} fileInfo1 file info - * @param {OCA.Files.FileInfo} fileInfo2 file info + * @param {OC.Files.FileInfo} fileInfo1 file info + * @param {OC.Files.FileInfo} fileInfo2 file info * @return {int} -1 if the first file must appear before the second one, * 0 if they are identify, 1 otherwise. */ @@ -2676,8 +2761,8 @@ /** * Compares two file infos by size. * - * @param {OCA.Files.FileInfo} fileInfo1 file info - * @param {OCA.Files.FileInfo} fileInfo2 file info + * @param {OC.Files.FileInfo} fileInfo1 file info + * @param {OC.Files.FileInfo} fileInfo2 file info * @return {int} -1 if the first file must appear before the second one, * 0 if they are identify, 1 otherwise. */ @@ -2687,8 +2772,8 @@ /** * Compares two file infos by timestamp. * - * @param {OCA.Files.FileInfo} fileInfo1 file info - * @param {OCA.Files.FileInfo} fileInfo2 file info + * @param {OC.Files.FileInfo} fileInfo1 file info + * @param {OC.Files.FileInfo} fileInfo2 file info * @return {int} -1 if the first file must appear before the second one, * 0 if they are identify, 1 otherwise. */ @@ -2700,23 +2785,14 @@ /** * File info attributes. * - * @todo make this a real class in the future - * @typedef {Object} OCA.Files.FileInfo + * @typedef {Object} OC.Files.FileInfo + * + * @lends OC.Files.FileInfo + * + * @deprecated use OC.Files.FileInfo instead * - * @property {int} id file id - * @property {String} name file name - * @property {String} [path] file path, defaults to the list's current path - * @property {String} mimetype mime type - * @property {String} type "file" for files or "dir" for directories - * @property {int} permissions file permissions - * @property {int} mtime modification time in milliseconds - * @property {boolean} [isShareMountPoint] whether the file is a share mount - * point - * @property {boolean} [isPreviewAvailable] whether a preview is available - * for the given file type - * @property {String} [icon] path to the mime type icon - * @property {String} etag etag of the file */ + OCA.Files.FileInfo = OC.Files.FileInfo; OCA.Files.FileList = FileList; })(); |