summaryrefslogtreecommitdiffstats
path: root/apps/files/js/filelist.js
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files/js/filelist.js')
-rw-r--r--apps/files/js/filelist.js572
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;
})();