2014-05-09 00:06:30 +04:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014
|
|
|
|
*
|
|
|
|
* This file is licensed under the Affero General Public License version 3
|
|
|
|
* or later.
|
|
|
|
*
|
|
|
|
* See the COPYING-README file.
|
|
|
|
*
|
|
|
|
*/
|
2013-10-28 23:22:06 +04:00
|
|
|
(function() {
|
2014-05-09 00:06:30 +04:00
|
|
|
var DELETED_REGEXP = new RegExp(/^(.+)\.d[0-9]+$/);
|
2013-10-28 23:22:06 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert a file name in the format filename.d12345 to the real file name.
|
|
|
|
* This will use basename.
|
|
|
|
* The name will not be changed if it has no ".d12345" suffix.
|
2014-06-24 01:56:10 +04:00
|
|
|
* @param {String} name file name
|
|
|
|
* @return {String} converted file name
|
2013-10-28 23:22:06 +04:00
|
|
|
*/
|
2014-05-09 00:06:30 +04:00
|
|
|
function getDeletedFileName(name) {
|
2013-10-28 23:22:06 +04:00
|
|
|
name = OC.basename(name);
|
2014-05-09 00:06:30 +04:00
|
|
|
var match = DELETED_REGEXP.exec(name);
|
2013-10-28 23:22:06 +04:00
|
|
|
if (match && match.length > 1) {
|
|
|
|
name = match[1];
|
2013-08-17 15:07:18 +04:00
|
|
|
}
|
2013-10-28 23:22:06 +04:00
|
|
|
return name;
|
2014-05-09 00:06:30 +04:00
|
|
|
}
|
2013-10-28 23:22:06 +04:00
|
|
|
|
2014-06-24 01:56:10 +04:00
|
|
|
/**
|
|
|
|
* @class OCA.Trashbin.FileList
|
|
|
|
* @augments OCA.Files.FileList
|
|
|
|
* @classdesc List of deleted files
|
|
|
|
*
|
|
|
|
* @param $el container element with existing markup for the #controls
|
|
|
|
* and a table
|
|
|
|
* @param [options] map of options
|
|
|
|
*/
|
2014-05-20 18:01:34 +04:00
|
|
|
var FileList = function($el, options) {
|
|
|
|
this.initialize($el, options);
|
2013-10-28 23:22:06 +04:00
|
|
|
};
|
2014-06-24 01:56:10 +04:00
|
|
|
FileList.prototype = _.extend({}, OCA.Files.FileList.prototype,
|
|
|
|
/** @lends OCA.Trashbin.FileList.prototype */ {
|
2014-05-12 21:54:20 +04:00
|
|
|
id: 'trashbin',
|
2014-05-09 00:06:30 +04:00
|
|
|
appName: t('files_trashbin', 'Deleted files'),
|
2013-10-28 23:22:06 +04:00
|
|
|
|
2014-06-24 01:56:10 +04:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
2014-05-09 00:06:30 +04:00
|
|
|
initialize: function() {
|
|
|
|
var result = OCA.Files.FileList.prototype.initialize.apply(this, arguments);
|
|
|
|
this.$el.find('.undelete').click('click', _.bind(this._onClickRestoreSelected, this));
|
2013-10-28 23:22:06 +04:00
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
this.setSort('mtime', 'desc');
|
|
|
|
/**
|
|
|
|
* Override crumb making to add "Deleted Files" entry
|
|
|
|
* and convert files with ".d" extensions to a more
|
|
|
|
* user friendly name.
|
|
|
|
*/
|
|
|
|
this.breadcrumb._makeCrumbs = function() {
|
|
|
|
var parts = OCA.Files.BreadCrumb.prototype._makeCrumbs.apply(this, arguments);
|
|
|
|
for (var i = 1; i < parts.length; i++) {
|
|
|
|
parts[i].name = getDeletedFileName(parts[i].name);
|
|
|
|
}
|
|
|
|
return parts;
|
|
|
|
};
|
2013-10-28 23:22:06 +04:00
|
|
|
|
2014-12-01 18:17:28 +03:00
|
|
|
OC.Plugins.attach('OCA.Trashbin.FileList', this);
|
2014-05-09 00:06:30 +04:00
|
|
|
return result;
|
|
|
|
},
|
2013-10-28 23:22:06 +04:00
|
|
|
|
2014-05-12 21:54:20 +04:00
|
|
|
/**
|
|
|
|
* Override to only return read permissions
|
|
|
|
*/
|
|
|
|
getDirectoryPermissions: function() {
|
|
|
|
return OC.PERMISSION_READ | OC.PERMISSION_DELETE;
|
|
|
|
},
|
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
_setCurrentDir: function(targetDir) {
|
|
|
|
OCA.Files.FileList.prototype._setCurrentDir.apply(this, arguments);
|
2014-02-12 17:50:23 +04:00
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
var baseDir = OC.basename(targetDir);
|
|
|
|
if (baseDir !== '') {
|
|
|
|
this.setPageTitle(getDeletedFileName(baseDir));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_createRow: function() {
|
|
|
|
// FIXME: MEGAHACK until we find a better solution
|
|
|
|
var tr = OCA.Files.FileList.prototype._createRow.apply(this, arguments);
|
|
|
|
tr.find('td.filesize').remove();
|
|
|
|
return tr;
|
|
|
|
},
|
|
|
|
|
|
|
|
_renderRow: function(fileData, options) {
|
|
|
|
options = options || {};
|
2016-06-23 12:50:59 +03:00
|
|
|
// make a copy to avoid changing original object
|
|
|
|
fileData = _.extend({}, fileData);
|
2014-05-09 00:06:30 +04:00
|
|
|
var dir = this.getCurrentDirectory();
|
|
|
|
var dirListing = dir !== '' && dir !== '/';
|
|
|
|
// show deleted time as mtime
|
|
|
|
if (fileData.mtime) {
|
|
|
|
fileData.mtime = parseInt(fileData.mtime, 10);
|
|
|
|
}
|
|
|
|
if (!dirListing) {
|
|
|
|
fileData.displayName = fileData.name;
|
|
|
|
fileData.name = fileData.name + '.d' + Math.floor(fileData.mtime / 1000);
|
|
|
|
}
|
|
|
|
return OCA.Files.FileList.prototype._renderRow.call(this, fileData, options);
|
|
|
|
},
|
2014-02-12 17:50:23 +04:00
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
getAjaxUrl: function(action, params) {
|
|
|
|
var q = '';
|
|
|
|
if (params) {
|
|
|
|
q = '?' + OC.buildQueryString(params);
|
|
|
|
}
|
|
|
|
return OC.filePath('files_trashbin', 'ajax', action + '.php') + q;
|
|
|
|
},
|
|
|
|
|
2014-05-12 21:54:20 +04:00
|
|
|
setupUploadEvents: function() {
|
|
|
|
// override and do nothing
|
|
|
|
},
|
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
linkTo: function(dir){
|
2014-05-12 21:54:20 +04:00
|
|
|
return OC.linkTo('files', 'index.php')+"?view=trashbin&dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
|
2014-05-09 00:06:30 +04:00
|
|
|
},
|
|
|
|
|
2015-08-25 12:29:35 +03:00
|
|
|
elementToFile: function($el) {
|
|
|
|
var fileInfo = OCA.Files.FileList.prototype.elementToFile($el);
|
|
|
|
if (this.getCurrentDirectory() === '/') {
|
|
|
|
fileInfo.displayName = getDeletedFileName(fileInfo.name);
|
|
|
|
}
|
|
|
|
// no size available
|
|
|
|
delete fileInfo.size;
|
|
|
|
return fileInfo;
|
|
|
|
},
|
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
updateEmptyContent: function(){
|
|
|
|
var exists = this.$fileList.find('tr:first').exists();
|
|
|
|
this.$el.find('#emptycontent').toggleClass('hidden', exists);
|
|
|
|
this.$el.find('#filestable th').toggleClass('hidden', !exists);
|
|
|
|
},
|
|
|
|
|
|
|
|
_removeCallback: function(result) {
|
|
|
|
if (result.status !== 'success') {
|
|
|
|
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
|
|
|
}
|
2014-02-12 17:50:23 +04:00
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
var files = result.data.success;
|
|
|
|
var $el;
|
2014-02-12 17:50:23 +04:00
|
|
|
for (var i = 0; i < files.length; i++) {
|
2014-05-09 00:06:30 +04:00
|
|
|
$el = this.remove(OC.basename(files[i].filename), {updateSummary: false});
|
|
|
|
this.fileSummary.remove({type: $el.attr('data-type'), size: $el.attr('data-size')});
|
2014-02-12 17:50:23 +04:00
|
|
|
}
|
2014-05-09 00:06:30 +04:00
|
|
|
this.fileSummary.update();
|
|
|
|
this.updateEmptyContent();
|
|
|
|
this.enableActions();
|
|
|
|
},
|
2014-02-12 17:50:23 +04:00
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
_onClickRestoreSelected: function(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
var self = this;
|
2014-05-12 21:54:20 +04:00
|
|
|
var allFiles = this.$el.find('.select-all').is(':checked');
|
2014-05-09 00:06:30 +04:00
|
|
|
var files = [];
|
|
|
|
var params = {};
|
|
|
|
this.disableActions();
|
|
|
|
if (allFiles) {
|
|
|
|
this.showMask();
|
|
|
|
params = {
|
|
|
|
allfiles: true,
|
|
|
|
dir: this.getCurrentDirectory()
|
|
|
|
};
|
2014-02-12 17:50:23 +04:00
|
|
|
}
|
2014-05-09 00:06:30 +04:00
|
|
|
else {
|
|
|
|
files = _.pluck(this.getSelectedFiles(), 'name');
|
|
|
|
for (var i = 0; i < files.length; i++) {
|
|
|
|
var deleteAction = this.findFileEl(files[i]).children("td.date").children(".action.delete");
|
2014-09-22 20:24:32 +04:00
|
|
|
deleteAction.removeClass('icon-delete').addClass('icon-loading-small');
|
2014-05-09 00:06:30 +04:00
|
|
|
}
|
|
|
|
params = {
|
|
|
|
files: JSON.stringify(files),
|
|
|
|
dir: this.getCurrentDirectory()
|
|
|
|
};
|
2014-02-12 17:50:23 +04:00
|
|
|
}
|
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
$.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'),
|
2014-02-12 17:50:23 +04:00
|
|
|
params,
|
|
|
|
function(result) {
|
|
|
|
if (allFiles) {
|
|
|
|
if (result.status !== 'success') {
|
|
|
|
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
|
|
|
}
|
2014-05-09 00:06:30 +04:00
|
|
|
self.hideMask();
|
2014-02-12 17:50:23 +04:00
|
|
|
// simply remove all files
|
2014-05-09 00:06:30 +04:00
|
|
|
self.setFiles([]);
|
|
|
|
self.enableActions();
|
2014-02-12 17:50:23 +04:00
|
|
|
}
|
|
|
|
else {
|
2014-05-09 00:06:30 +04:00
|
|
|
self._removeCallback(result);
|
2014-02-12 17:50:23 +04:00
|
|
|
}
|
|
|
|
}
|
2014-05-09 00:06:30 +04:00
|
|
|
);
|
|
|
|
},
|
2014-02-12 17:50:23 +04:00
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
_onClickDeleteSelected: function(event) {
|
2014-02-12 17:50:23 +04:00
|
|
|
event.preventDefault();
|
2014-05-09 00:06:30 +04:00
|
|
|
var self = this;
|
2014-05-12 21:54:20 +04:00
|
|
|
var allFiles = this.$el.find('.select-all').is(':checked');
|
2014-05-09 00:06:30 +04:00
|
|
|
var files = [];
|
|
|
|
var params = {};
|
|
|
|
if (allFiles) {
|
|
|
|
params = {
|
|
|
|
allfiles: true,
|
|
|
|
dir: this.getCurrentDirectory()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
files = _.pluck(this.getSelectedFiles(), 'name');
|
|
|
|
params = {
|
|
|
|
files: JSON.stringify(files),
|
|
|
|
dir: this.getCurrentDirectory()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
this.disableActions();
|
|
|
|
if (allFiles) {
|
|
|
|
this.showMask();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (var i = 0; i < files.length; i++) {
|
|
|
|
var deleteAction = this.findFileEl(files[i]).children("td.date").children(".action.delete");
|
2014-09-22 20:24:32 +04:00
|
|
|
deleteAction.removeClass('icon-delete').addClass('icon-loading-small');
|
2014-05-09 00:06:30 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'),
|
|
|
|
params,
|
|
|
|
function(result) {
|
|
|
|
if (allFiles) {
|
|
|
|
if (result.status !== 'success') {
|
|
|
|
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
|
|
|
}
|
|
|
|
self.hideMask();
|
|
|
|
// simply remove all files
|
|
|
|
self.setFiles([]);
|
|
|
|
self.enableActions();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
self._removeCallback(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
|
|
|
_onClickFile: function(event) {
|
|
|
|
var mime = $(this).parent().parent().data('mime');
|
|
|
|
if (mime !== 'httpd/unix-directory') {
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
return OCA.Files.FileList.prototype._onClickFile.apply(this, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
generatePreviewUrl: function(urlSpec) {
|
|
|
|
return OC.generateUrl('/apps/files_trashbin/ajax/preview.php?') + $.param(urlSpec);
|
|
|
|
},
|
|
|
|
|
2014-05-12 21:54:20 +04:00
|
|
|
getDownloadUrl: function() {
|
2014-05-09 00:06:30 +04:00
|
|
|
// no downloads
|
|
|
|
return '#';
|
|
|
|
},
|
|
|
|
|
|
|
|
enableActions: function() {
|
|
|
|
this.$el.find('.action').css('display', 'inline');
|
2015-10-01 23:54:36 +03:00
|
|
|
this.$el.find('input:checkbox').removeClass('u-hidden');
|
2014-05-09 00:06:30 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
disableActions: function() {
|
|
|
|
this.$el.find('.action').css('display', 'none');
|
2015-10-01 23:54:36 +03:00
|
|
|
this.$el.find('input:checkbox').addClass('u-hidden');
|
2014-05-12 21:54:20 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
updateStorageStatistics: function() {
|
|
|
|
// no op because the trashbin doesn't have
|
|
|
|
// storage info like free space / used space
|
2014-12-08 17:16:15 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
isSelectedDeletable: function() {
|
|
|
|
return true;
|
2015-07-13 18:38:13 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reloads the file list using ajax call
|
|
|
|
*
|
|
|
|
* @return ajax call object
|
|
|
|
*/
|
|
|
|
reload: function() {
|
|
|
|
this._selectedFiles = {};
|
|
|
|
this._selectionSummary.clear();
|
|
|
|
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
|
|
|
|
}
|
|
|
|
});
|
|
|
|
var callBack = this.reloadCallback.bind(this);
|
|
|
|
return this._reloadCall.then(callBack, callBack);
|
|
|
|
},
|
|
|
|
reloadCallback: function(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.show(result.data.message);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-03-02 19:42:51 +03:00
|
|
|
if (result.status === 401) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-07-13 18:38:13 +03:00
|
|
|
// Firewall Blocked request?
|
|
|
|
if (result.status === 403) {
|
|
|
|
// Go home
|
|
|
|
this.changeDirectory('/');
|
|
|
|
OC.Notification.show(t('files', 'This operation is forbidden'));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Did share service die or something else fail?
|
|
|
|
if (result.status === 500) {
|
|
|
|
// Go home
|
|
|
|
this.changeDirectory('/');
|
|
|
|
OC.Notification.show(t('files', 'This directory is unavailable, please check the logs or contact the administrator'));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result.status === 404) {
|
|
|
|
// go back home
|
|
|
|
this.changeDirectory('/');
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// aborted ?
|
|
|
|
if (result.status === 0){
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.setFiles(result.data.files);
|
|
|
|
return true;
|
|
|
|
},
|
2014-02-12 17:50:23 +04:00
|
|
|
|
2014-05-09 00:06:30 +04:00
|
|
|
});
|
|
|
|
|
|
|
|
OCA.Trashbin.FileList = FileList;
|
2013-10-28 23:22:06 +04:00
|
|
|
})();
|
2014-05-09 00:06:30 +04:00
|
|
|
|