summaryrefslogtreecommitdiffstats
path: root/apps/files_trashbin
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2014-05-16 13:00:35 +0200
committerVincent Petry <pvince81@owncloud.com>2014-05-16 13:00:35 +0200
commit1fb0d5412c7a4a3b888098e492342699d05fe55e (patch)
tree436bab2e329cf0e3ff2080a4227338c131f85b57 /apps/files_trashbin
parent43d6650d194105dac30b11fb2ba4a3b3c7805650 (diff)
parent6fd084243b65a556d4775209ba3916145ef5912a (diff)
downloadnextcloud-server-1fb0d5412c7a4a3b888098e492342699d05fe55e.tar.gz
nextcloud-server-1fb0d5412c7a4a3b888098e492342699d05fe55e.zip
Merge pull request #6260 from owncloud/jan-navigation-filesidebar
Files app navigation sidebar
Diffstat (limited to 'apps/files_trashbin')
-rw-r--r--apps/files_trashbin/appinfo/app.php14
-rw-r--r--apps/files_trashbin/css/trash.css13
-rw-r--r--apps/files_trashbin/index.php42
-rw-r--r--apps/files_trashbin/js/app.js82
-rw-r--r--apps/files_trashbin/js/disableDefaultActions.js3
-rw-r--r--apps/files_trashbin/js/filelist.js373
-rw-r--r--apps/files_trashbin/js/trash.js130
-rw-r--r--apps/files_trashbin/list.php11
-rw-r--r--apps/files_trashbin/templates/index.php8
-rw-r--r--apps/files_trashbin/tests/js/appSpec.js69
-rw-r--r--apps/files_trashbin/tests/js/filelistSpec.js309
11 files changed, 712 insertions, 342 deletions
diff --git a/apps/files_trashbin/appinfo/app.php b/apps/files_trashbin/appinfo/app.php
index d30a601ef56..b8900ee0de3 100644
--- a/apps/files_trashbin/appinfo/app.php
+++ b/apps/files_trashbin/appinfo/app.php
@@ -1,7 +1,15 @@
<?php
-
-//OC::$CLASSPATH['OCA\Files_Trashbin\Hooks'] = 'files_trashbin/lib/hooks.php';
-//OC::$CLASSPATH['OCA\Files_Trashbin\Trashbin'] = 'files_trashbin/lib/trash.php';
+$l = OC_L10N::get('files_trashbin');
// register hooks
\OCA\Files_Trashbin\Trashbin::registerHooks();
+
+\OCA\Files\App::getNavigationManager()->add(
+array(
+ "id" => 'trashbin',
+ "appname" => 'files_trashbin',
+ "script" => 'list.php',
+ "order" => 1,
+ "name" => $l->t('Deleted files')
+)
+);
diff --git a/apps/files_trashbin/css/trash.css b/apps/files_trashbin/css/trash.css
index 7ca3e355fc2..04b4a175c83 100644
--- a/apps/files_trashbin/css/trash.css
+++ b/apps/files_trashbin/css/trash.css
@@ -1,4 +1,13 @@
-#fileList tr[data-type="file"] td a.name,
-#fileList tr[data-type="file"] td a.name span {
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+#app-content-trashbin tbody tr[data-type="file"] td a.name,
+#app-content-trashbin tbody tr[data-type="file"] td a.name span {
cursor: default;
}
diff --git a/apps/files_trashbin/index.php b/apps/files_trashbin/index.php
deleted file mode 100644
index 6e6a8a38307..00000000000
--- a/apps/files_trashbin/index.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-// Check if we are a user
-OCP\User::checkLoggedIn();
-
-OCP\App::setActiveNavigationEntry('files_index');
-
-OCP\Util::addScript('files_trashbin', 'disableDefaultActions');
-OCP\Util::addScript('files', 'fileactions');
-$tmpl = new OCP\Template('files_trashbin', 'index', 'user');
-
-OCP\Util::addStyle('files', 'files');
-OCP\Util::addStyle('files_trashbin', 'trash');
-OCP\Util::addScript('files', 'filesummary');
-OCP\Util::addScript('files', 'breadcrumb');
-OCP\Util::addScript('files', 'filelist');
-// filelist overrides
-OCP\Util::addScript('files_trashbin', 'filelist');
-OCP\Util::addscript('files', 'files');
-OCP\Util::addScript('files_trashbin', 'trash');
-
-$dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : '';
-
-$isIE8 = false;
-preg_match('/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $matches);
-if (count($matches) > 0 && $matches[1] <= 8){
- $isIE8 = true;
-}
-
-// if IE8 and "?dir=path" was specified, reformat the URL to use a hash like "#?dir=path"
-if ($isIE8 && isset($_GET['dir'])){
- if ($dir === ''){
- $dir = '/';
- }
- header('Location: ' . OCP\Util::linkTo('files_trashbin', 'index.php') . '#?dir=' . \OCP\Util::encodePath($dir));
- exit();
-}
-
-$tmpl->assign('dir', $dir);
-$tmpl->assign('disableSharing', true);
-
-$tmpl->printPage();
diff --git a/apps/files_trashbin/js/app.js b/apps/files_trashbin/js/app.js
new file mode 100644
index 00000000000..aa499ae1791
--- /dev/null
+++ b/apps/files_trashbin/js/app.js
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+OCA.Trashbin = {};
+OCA.Trashbin.App = {
+ _initialized: false,
+
+ initialize: function($el) {
+ if (this._initialized) {
+ return;
+ }
+ this._initialized = true;
+ this.fileList = new OCA.Trashbin.FileList(
+ $('#app-content-trashbin'), {
+ scrollContainer: $('#app-content')
+ }
+ );
+ this.registerFileActions(this.fileList);
+ },
+
+ registerFileActions: function(fileList) {
+ var self = this;
+ var fileActions = _.extend({}, OCA.Files.FileActions);
+ fileActions.clear();
+ fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename) {
+ var dir = fileList.getCurrentDirectory();
+ if (dir !== '/') {
+ dir = dir + '/';
+ }
+ fileList.changeDirectory(dir + filename);
+ });
+
+ fileActions.setDefault('dir', 'Open');
+
+ fileActions.register('all', 'Restore', OC.PERMISSION_READ, OC.imagePath('core', 'actions/history'), function(filename) {
+ var tr = fileList.findFileEl(filename);
+ var deleteAction = tr.children("td.date").children(".action.delete");
+ deleteAction.removeClass('delete-icon').addClass('progress-icon');
+ fileList.disableActions();
+ $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), {
+ files: JSON.stringify([filename]),
+ dir: fileList.getCurrentDirectory()
+ },
+ _.bind(fileList._removeCallback, fileList)
+ );
+ }, t('files_trashbin', 'Restore'));
+
+ fileActions.register('all', 'Delete', OC.PERMISSION_READ, function() {
+ return OC.imagePath('core', 'actions/delete');
+ }, function(filename) {
+ $('.tipsy').remove();
+ var tr = fileList.findFileEl(filename);
+ var deleteAction = tr.children("td.date").children(".action.delete");
+ deleteAction.removeClass('delete-icon').addClass('progress-icon');
+ fileList.disableActions();
+ $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'), {
+ files: JSON.stringify([filename]),
+ dir: fileList.getCurrentDirectory()
+ },
+ _.bind(fileList._removeCallback, fileList)
+ );
+ });
+ fileList.setFileActions(fileActions);
+ }
+};
+
+$(document).ready(function() {
+ $('#app-content-trashbin').one('show', function() {
+ var App = OCA.Trashbin.App;
+ App.initialize($('#app-content-trashbin'));
+ // force breadcrumb init
+ // App.fileList.changeDirectory(App.fileList.getCurrentDirectory(), false, true);
+ });
+});
+
diff --git a/apps/files_trashbin/js/disableDefaultActions.js b/apps/files_trashbin/js/disableDefaultActions.js
deleted file mode 100644
index 50ceaf4696f..00000000000
--- a/apps/files_trashbin/js/disableDefaultActions.js
+++ /dev/null
@@ -1,3 +0,0 @@
-/* disable download and sharing actions */
-var disableDownloadActions = true;
-var trashBinApp = true;
diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js
index 00fc7e16b88..205f879f335 100644
--- a/apps/files_trashbin/js/filelist.js
+++ b/apps/files_trashbin/js/filelist.js
@@ -1,8 +1,14 @@
-/* global OC, t, FileList */
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
(function() {
- FileList.appName = t('files_trashbin', 'Deleted files');
-
- FileList._deletedRegExp = new RegExp(/^(.+)\.d[0-9]+$/);
+ var DELETED_REGEXP = new RegExp(/^(.+)\.d[0-9]+$/);
/**
* Convert a file name in the format filename.d12345 to the real file name.
@@ -11,195 +17,248 @@
* @param name file name
* @return converted file name
*/
- FileList.getDeletedFileName = function(name) {
+ function getDeletedFileName(name) {
name = OC.basename(name);
- var match = FileList._deletedRegExp.exec(name);
+ var match = DELETED_REGEXP.exec(name);
if (match && match.length > 1) {
name = match[1];
}
return name;
- };
-
- var oldSetCurrentDir = FileList._setCurrentDir;
- FileList._setCurrentDir = function(targetDir) {
- oldSetCurrentDir.apply(this, arguments);
-
- var baseDir = OC.basename(targetDir);
- if (baseDir !== '') {
- FileList.setPageTitle(FileList.getDeletedFileName(baseDir));
- }
- };
+ }
- var oldCreateRow = FileList._createRow;
- FileList._createRow = function() {
- // FIXME: MEGAHACK until we find a better solution
- var tr = oldCreateRow.apply(this, arguments);
- tr.find('td.filesize').remove();
- return tr;
+ var FileList = function($el) {
+ this.initialize($el);
};
+ FileList.prototype = _.extend({}, OCA.Files.FileList.prototype, {
+ id: 'trashbin',
+ appName: t('files_trashbin', 'Deleted files'),
- FileList._onClickBreadCrumb = function(e) {
- var $el = $(e.target).closest('.crumb'),
- index = $el.index(),
- $targetDir = $el.data('dir');
- // first one is home, let the link makes it default action
- if (index !== 0) {
- e.preventDefault();
- FileList.changeDirectory($targetDir);
- }
- };
+ initialize: function() {
+ var result = OCA.Files.FileList.prototype.initialize.apply(this, arguments);
+ this.$el.find('.undelete').click('click', _.bind(this._onClickRestoreSelected, this));
- var oldRenderRow = FileList._renderRow;
- FileList._renderRow = function(fileData, options) {
- options = options || {};
- var dir = FileList.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 oldRenderRow.call(this, fileData, options);
- };
+ 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;
+ };
- FileList.linkTo = function(dir){
- return OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
- };
+ return result;
+ },
- FileList.updateEmptyContent = function(){
- var $fileList = $('#fileList');
- var exists = $fileList.find('tr:first').exists();
- $('#emptycontent').toggleClass('hidden', exists);
- $('#filestable th').toggleClass('hidden', !exists);
- };
+ /**
+ * Override to only return read permissions
+ */
+ getDirectoryPermissions: function() {
+ return OC.PERMISSION_READ | OC.PERMISSION_DELETE;
+ },
- var oldInit = FileList.initialize;
- FileList.initialize = function() {
- var result = oldInit.apply(this, arguments);
- $('.undelete').click('click', FileList._onClickRestoreSelected);
- this.setSort('mtime', 'desc');
- return result;
- };
+ _setCurrentDir: function(targetDir) {
+ OCA.Files.FileList.prototype._setCurrentDir.apply(this, arguments);
- FileList._removeCallback = function(result) {
- if (result.status !== 'success') {
- OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
- }
+ var baseDir = OC.basename(targetDir);
+ if (baseDir !== '') {
+ this.setPageTitle(getDeletedFileName(baseDir));
+ }
+ },
- var files = result.data.success;
- var $el;
- for (var i = 0; i < files.length; i++) {
- $el = FileList.remove(OC.basename(files[i].filename), {updateSummary: false});
- FileList.fileSummary.remove({type: $el.attr('data-type'), size: $el.attr('data-size')});
- }
- FileList.fileSummary.update();
- FileList.updateEmptyContent();
- enableActions();
- }
+ _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;
+ },
- FileList._onClickRestoreSelected = function(event) {
- event.preventDefault();
- var allFiles = $('#select_all').is(':checked');
- var files = [];
- var params = {};
- disableActions();
- if (allFiles) {
- FileList.showMask();
- params = {
- allfiles: true,
- dir: FileList.getCurrentDirectory()
- };
- }
- else {
- files = _.pluck(FileList.getSelectedFiles(), 'name');
- for (var i = 0; i < files.length; i++) {
- var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete");
- deleteAction.removeClass('delete-icon').addClass('progress-icon');
+ _renderRow: function(fileData, options) {
+ options = options || {};
+ var dir = this.getCurrentDirectory();
+ var dirListing = dir !== '' && dir !== '/';
+ // show deleted time as mtime
+ if (fileData.mtime) {
+ fileData.mtime = parseInt(fileData.mtime, 10);
}
- params = {
- files: JSON.stringify(files),
- dir: FileList.getCurrentDirectory()
- };
- }
+ 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);
+ },
- $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'),
- params,
- function(result) {
- if (allFiles) {
- if (result.status !== 'success') {
- OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
- }
- FileList.hideMask();
- // simply remove all files
- FileList.setFiles([]);
- enableActions();
- }
- else {
- FileList._removeCallback(result);
- }
+ getAjaxUrl: function(action, params) {
+ var q = '';
+ if (params) {
+ q = '?' + OC.buildQueryString(params);
}
- );
- };
+ return OC.filePath('files_trashbin', 'ajax', action + '.php') + q;
+ },
- FileList._onClickDeleteSelected = function(event) {
- event.preventDefault();
- var allFiles = $('#select_all').is(':checked');
- var files = [];
- var params = {};
- if (allFiles) {
- params = {
- allfiles: true,
- dir: FileList.getCurrentDirectory()
- };
- }
- else {
- files = _.pluck(FileList.getSelectedFiles(), 'name');
- params = {
- files: JSON.stringify(files),
- dir: FileList.getCurrentDirectory()
- };
- }
+ setupUploadEvents: function() {
+ // override and do nothing
+ },
- disableActions();
- if (allFiles) {
- FileList.showMask();
- }
- else {
+ linkTo: function(dir){
+ return OC.linkTo('files', 'index.php')+"?view=trashbin&dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
+ },
+
+ 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'));
+ }
+
+ var files = result.data.success;
+ var $el;
for (var i = 0; i < files.length; i++) {
- var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete");
- deleteAction.removeClass('delete-icon').addClass('progress-icon');
+ $el = this.remove(OC.basename(files[i].filename), {updateSummary: false});
+ this.fileSummary.remove({type: $el.attr('data-type'), size: $el.attr('data-size')});
}
- }
+ this.fileSummary.update();
+ this.updateEmptyContent();
+ this.enableActions();
+ },
- $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'),
+ _onClickRestoreSelected: function(event) {
+ event.preventDefault();
+ var self = this;
+ var allFiles = this.$el.find('.select-all').is(':checked');
+ var files = [];
+ var params = {};
+ this.disableActions();
+ if (allFiles) {
+ this.showMask();
+ params = {
+ allfiles: true,
+ dir: this.getCurrentDirectory()
+ };
+ }
+ 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");
+ deleteAction.removeClass('delete-icon').addClass('progress-icon');
+ }
+ params = {
+ files: JSON.stringify(files),
+ dir: this.getCurrentDirectory()
+ };
+ }
+
+ $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'),
params,
function(result) {
if (allFiles) {
if (result.status !== 'success') {
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
}
- FileList.hideMask();
+ self.hideMask();
// simply remove all files
- FileList.setFiles([]);
- enableActions();
+ self.setFiles([]);
+ self.enableActions();
}
else {
- FileList._removeCallback(result);
+ self._removeCallback(result);
}
}
- );
- };
+ );
+ },
- var oldClickFile = FileList._onClickFile;
- FileList._onClickFile = function(event) {
- var mime = $(this).parent().parent().data('mime');
- if (mime !== 'httpd/unix-directory') {
+ _onClickDeleteSelected: function(event) {
event.preventDefault();
+ var self = this;
+ var allFiles = this.$el.find('.select-all').is(':checked');
+ 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");
+ deleteAction.removeClass('delete-icon').addClass('progress-icon');
+ }
+ }
+
+ $.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);
+ },
+
+ getDownloadUrl: function() {
+ // no downloads
+ return '#';
+ },
+
+ enableActions: function() {
+ this.$el.find('.action').css('display', 'inline');
+ this.$el.find(':input:checkbox').css('display', 'inline');
+ },
+
+ disableActions: function() {
+ this.$el.find('.action').css('display', 'none');
+ this.$el.find(':input:checkbox').css('display', 'none');
+ },
+
+ updateStorageStatistics: function() {
+ // no op because the trashbin doesn't have
+ // storage info like free space / used space
}
- return oldClickFile.apply(this, arguments);
- };
+ });
+
+ OCA.Trashbin.FileList = FileList;
})();
+
diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js
deleted file mode 100644
index 5f2436de809..00000000000
--- a/apps/files_trashbin/js/trash.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2014
- *
- * This file is licensed under the Affero General Public License version 3
- * or later.
- *
- * See the COPYING-README file.
- *
- */
-
-/* global OC, t, BreadCrumb, FileActions, FileList, Files */
-$(document).ready(function() {
- var deletedRegExp = new RegExp(/^(.+)\.d[0-9]+$/);
-
- /**
- * 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.
- * @param name file name
- * @return converted file name
- */
- function getDeletedFileName(name) {
- name = OC.basename(name);
- var match = deletedRegExp.exec(name);
- if (match && match.length > 1) {
- name = match[1];
- }
- return name;
- }
-
- Files.updateStorageStatistics = function() {
- // no op because the trashbin doesn't have
- // storage info like free space / used space
- };
-
- if (typeof FileActions !== 'undefined') {
- FileActions.register('all', 'Restore', OC.PERMISSION_READ, OC.imagePath('core', 'actions/history'), function(filename) {
- var tr = FileList.findFileEl(filename);
- var deleteAction = tr.children("td.date").children(".action.delete");
- deleteAction.removeClass('delete-icon').addClass('progress-icon');
- disableActions();
- $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), {
- files: JSON.stringify([filename]),
- dir: FileList.getCurrentDirectory()
- },
- FileList._removeCallback
- );
- }, t('files_trashbin', 'Restore'));
- };
-
- FileActions.register('all', 'Delete', OC.PERMISSION_READ, function() {
- return OC.imagePath('core', 'actions/delete');
- }, function(filename) {
- $('.tipsy').remove();
- var tr = FileList.findFileEl(filename);
- var deleteAction = tr.children("td.date").children(".action.delete");
- deleteAction.removeClass('delete-icon').addClass('progress-icon');
- disableActions();
- $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'), {
- files: JSON.stringify([filename]),
- dir: FileList.getCurrentDirectory()
- },
- FileList._removeCallback
- );
- });
-
- /**
- * Override crumb URL maker (hacky!)
- */
- FileList.breadcrumb.getCrumbUrl = function(part, index) {
- if (index === 0) {
- return OC.linkTo('files', 'index.php');
- }
- return OC.linkTo('files_trashbin', 'index.php')+"?dir=" + encodeURIComponent(part.dir);
- };
-
- Files.generatePreviewUrl = function(urlSpec) {
- return OC.generateUrl('/apps/files_trashbin/ajax/preview.php?') + $.param(urlSpec);
- };
-
- Files.getDownloadUrl = function(action, params) {
- // no downloads
- return '#';
- };
-
- Files.getAjaxUrl = function(action, params) {
- var q = '';
- if (params) {
- q = '?' + OC.buildQueryString(params);
- }
- return OC.filePath('files_trashbin', 'ajax', action + '.php') + q;
- };
-
-
- /**
- * Override crumb making to add "Deleted Files" entry
- * and convert files with ".d" extensions to a more
- * user friendly name.
- */
- var oldMakeCrumbs = BreadCrumb.prototype._makeCrumbs;
- BreadCrumb.prototype._makeCrumbs = function() {
- var parts = oldMakeCrumbs.apply(this, arguments);
- // duplicate first part
- parts.unshift(parts[0]);
- parts[1] = {
- dir: '/',
- name: t('files_trashbin', 'Deleted Files')
- };
- for (var i = 2; i < parts.length; i++) {
- parts[i].name = getDeletedFileName(parts[i].name);
- }
- return parts;
- };
-
- FileActions.actions.dir = {
- // only keep 'Open' action for navigation
- 'Open': FileActions.actions.dir.Open
- };
-});
-
-function enableActions() {
- $(".action").css("display", "inline");
- $(":input:checkbox").css("display", "inline");
-}
-
-function disableActions() {
- $(".action").css("display", "none");
- $(":input:checkbox").css("display", "none");
-}
-
diff --git a/apps/files_trashbin/list.php b/apps/files_trashbin/list.php
new file mode 100644
index 00000000000..b4047b82ef9
--- /dev/null
+++ b/apps/files_trashbin/list.php
@@ -0,0 +1,11 @@
+<?php
+
+// Check if we are a user
+OCP\User::checkLoggedIn();
+
+
+$tmpl = new OCP\Template('files_trashbin', 'index', '');
+OCP\Util::addStyle('files_trashbin', 'trash');
+OCP\Util::addScript('files_trashbin', 'app');
+OCP\Util::addScript('files_trashbin', 'filelist');
+$tmpl->printPage();
diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php
index 7c673c317e0..fc18e88c41e 100644
--- a/apps/files_trashbin/templates/index.php
+++ b/apps/files_trashbin/templates/index.php
@@ -6,17 +6,15 @@
<div id="emptycontent" class="hidden"><?php p($l->t('Nothing in here. Your trash bin is empty!'))?></div>
-<input type="hidden" id="permissions" value="0">
-<input type="hidden" id="disableSharing" data-status="<?php p($_['disableSharing']); ?>">
-<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
+<input type="hidden" name="dir" value="" id="dir">
<table id="filestable">
<thead>
<tr>
<th id='headerName' class="hidden column-name">
<div id="headerName-container">
- <input type="checkbox" id="select_all" />
- <label for="select_all"></label>
+ <input type="checkbox" id="select_all_trash" class="select-all"/>
+ <label for="select_all_trash"></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">
diff --git a/apps/files_trashbin/tests/js/appSpec.js b/apps/files_trashbin/tests/js/appSpec.js
new file mode 100644
index 00000000000..ca7d71831f8
--- /dev/null
+++ b/apps/files_trashbin/tests/js/appSpec.js
@@ -0,0 +1,69 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+describe('OCA.Trashbin.App tests', function() {
+ var App = OCA.Trashbin.App;
+
+ beforeEach(function() {
+ $('#testArea').append(
+ '<div id="app-navigation">' +
+ '<ul><li data-id="files"><a>Files</a></li>' +
+ '<li data-id="trashbin"><a>Trashbin</a></li>' +
+ '</div>' +
+ '<div id="app-content">' +
+ '<div id="app-content-files" class="hidden">' +
+ '</div>' +
+ '<div id="app-content-trashbin" class="hidden">' +
+ '</div>' +
+ '</div>' +
+ '</div>'
+ );
+ App.initialize($('#app-content-trashbin'));
+ });
+ afterEach(function() {
+ App._initialized = false;
+ App.fileList = null;
+ });
+
+ describe('initialization', function() {
+ it('creates a custom filelist instance', function() {
+ App.initialize();
+ expect(App.fileList).toBeDefined();
+ expect(App.fileList.$el.is('#app-content-trashbin')).toEqual(true);
+ });
+
+ it('registers custom file actions', function() {
+ var fileActions;
+ App.initialize();
+
+ fileActions = App.fileList.fileActions;
+
+ expect(fileActions.actions.all).toBeDefined();
+ expect(fileActions.actions.all.Restore).toBeDefined();
+ expect(fileActions.actions.all.Delete).toBeDefined();
+
+ expect(fileActions.actions.all.Rename).not.toBeDefined();
+ expect(fileActions.actions.all.Download).not.toBeDefined();
+
+ expect(fileActions.defaults.dir).toEqual('Open');
+ });
+ });
+});
diff --git a/apps/files_trashbin/tests/js/filelistSpec.js b/apps/files_trashbin/tests/js/filelistSpec.js
new file mode 100644
index 00000000000..d41c24c3cc9
--- /dev/null
+++ b/apps/files_trashbin/tests/js/filelistSpec.js
@@ -0,0 +1,309 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+describe('OCA.Trashbin.FileList tests', function() {
+ var testFiles, alertStub, notificationStub, fileList;
+ var FileActions = OCA.Files.FileActions;
+
+ beforeEach(function() {
+ alertStub = sinon.stub(OC.dialogs, 'alert');
+ notificationStub = sinon.stub(OC.Notification, 'show');
+
+ // init parameters and test table elements
+ $('#testArea').append(
+ '<div id="app-content-trashbin">' +
+ // init horrible parameters
+ '<input type="hidden" id="dir" value="/"></input>' +
+ // set this but it shouldn't be used (could be the one from the
+ // files app)
+ '<input type="hidden" id="permissions" value="31"></input>' +
+ // dummy controls
+ '<div id="controls">' +
+ ' <div class="actions creatable"></div>' +
+ ' <div class="notCreatable"></div>' +
+ '</div>' +
+ // dummy table
+ // TODO: at some point this will be rendered by the fileList class itself!
+ '<table id="filestable">' +
+ '<thead><tr><th id="headerName" class="hidden">' +
+ '<input type="checkbox" id="select_all_trash" class="select-all">' +
+ '<span class="name">Name</span>' +
+ '<span class="selectedActions hidden">' +
+ '<a href class="undelete">Restore</a>' +
+ '<a href class="delete-selected">Delete</a></span>' +
+ '</th></tr></thead>' +
+ '<tbody id="fileList"></tbody>' +
+ '<tfoot></tfoot>' +
+ '</table>' +
+ '<div id="emptycontent">Empty content message</div>' +
+ '</div>'
+ );
+
+ testFiles = [{
+ id: 1,
+ type: 'file',
+ name: 'One.txt',
+ mtime: 11111000,
+ mimetype: 'text/plain',
+ etag: 'abc'
+ }, {
+ id: 2,
+ type: 'file',
+ name: 'Two.jpg',
+ mtime: 22222000,
+ mimetype: 'image/jpeg',
+ etag: 'def',
+ }, {
+ id: 3,
+ type: 'file',
+ name: 'Three.pdf',
+ mtime: 33333000,
+ mimetype: 'application/pdf',
+ etag: '123',
+ }, {
+ id: 4,
+ type: 'dir',
+ mtime: 99999000,
+ name: 'somedir',
+ mimetype: 'httpd/unix-directory',
+ etag: '456'
+ }];
+
+ fileList = new OCA.Trashbin.FileList($('#app-content-trashbin'));
+ OCA.Trashbin.App.registerFileActions(fileList);
+ });
+ afterEach(function() {
+ testFiles = undefined;
+ fileList = undefined;
+
+ FileActions.clear();
+ $('#dir').remove();
+ notificationStub.restore();
+ alertStub.restore();
+ });
+ describe('Initialization', function() {
+ it('Sorts by mtime by default', function() {
+ expect(fileList._sort).toEqual('mtime');
+ expect(fileList._sortDirection).toEqual('desc');
+ });
+ it('Always returns read and delete permission', function() {
+ expect(fileList.getDirectoryPermissions()).toEqual(OC.PERMISSION_READ | OC.PERMISSION_DELETE);
+ });
+ });
+ describe('Breadcrumbs', function() {
+ beforeEach(function() {
+ var data = {
+ status: 'success',
+ data: {
+ files: testFiles,
+ permissions: 1
+ }
+ };
+ fakeServer.respondWith(/\/index\.php\/apps\/files_trashbin\/ajax\/list.php\?dir=%2Fsubdir/, [
+ 200, {
+ "Content-Type": "application/json"
+ },
+ JSON.stringify(data)
+ ]);
+ });
+ it('links the breadcrumb to the trashbin view', function() {
+ fileList.changeDirectory('/subdir', false, true);
+ fakeServer.respond();
+ var $crumbs = fileList.$el.find('#controls .crumb');
+ expect($crumbs.length).toEqual(2);
+ expect($crumbs.eq(0).find('a').text()).toEqual('');
+ expect($crumbs.eq(0).find('a').attr('href'))
+ .toEqual(OC.webroot + '/index.php/apps/files?view=trashbin&dir=/');
+ expect($crumbs.eq(1).find('a').text()).toEqual('subdir');
+ expect($crumbs.eq(1).find('a').attr('href'))
+ .toEqual(OC.webroot + '/index.php/apps/files?view=trashbin&dir=/subdir');
+ });
+ });
+ describe('Rendering rows', function() {
+ it('renders rows with the correct data when in root', function() {
+ // dir listing is false when in root
+ $('#dir').val('/');
+ fileList.setFiles(testFiles);
+ var $rows = fileList.$el.find('tbody tr');
+ var $tr = $rows.eq(0);
+ expect($rows.length).toEqual(4);
+ expect($tr.attr('data-id')).toEqual('1');
+ expect($tr.attr('data-type')).toEqual('file');
+ expect($tr.attr('data-file')).toEqual('One.txt.d11111');
+ expect($tr.attr('data-size')).not.toBeDefined();
+ expect($tr.attr('data-etag')).toEqual('abc');
+ expect($tr.attr('data-permissions')).toEqual('9'); // read and delete
+ expect($tr.attr('data-mime')).toEqual('text/plain');
+ expect($tr.attr('data-mtime')).toEqual('11111000');
+ expect($tr.find('a.name').attr('href')).toEqual('#');
+
+ expect($tr.find('.nametext').text().trim()).toEqual('One.txt');
+
+ expect(fileList.findFileEl('One.txt.d11111')[0]).toEqual($tr[0]);
+ });
+ it('renders rows with the correct data when in subdirectory', function() {
+ // dir listing is true when in a subdir
+ $('#dir').val('/subdir');
+
+ fileList.setFiles(testFiles);
+ var $rows = fileList.$el.find('tbody tr');
+ var $tr = $rows.eq(0);
+ expect($rows.length).toEqual(4);
+ expect($tr.attr('data-id')).toEqual('1');
+ expect($tr.attr('data-type')).toEqual('file');
+ expect($tr.attr('data-file')).toEqual('One.txt');
+ expect($tr.attr('data-size')).not.toBeDefined();
+ expect($tr.attr('data-etag')).toEqual('abc');
+ expect($tr.attr('data-permissions')).toEqual('9'); // read and delete
+ expect($tr.attr('data-mime')).toEqual('text/plain');
+ expect($tr.attr('data-mtime')).toEqual('11111000');
+ expect($tr.find('a.name').attr('href')).toEqual('#');
+
+ expect($tr.find('.nametext').text().trim()).toEqual('One.txt');
+
+ expect(fileList.findFileEl('One.txt')[0]).toEqual($tr[0]);
+ });
+ it('does not render a size column', function() {
+ expect(fileList.$el.find('tbody tr .filesize').length).toEqual(0);
+ });
+ });
+ describe('File actions', function() {
+ describe('Deleting single files', function() {
+ // TODO: checks ajax call
+ // TODO: checks spinner
+ // TODO: remove item after delete
+ // TODO: bring back item if delete failed
+ });
+ describe('Restoring single files', function() {
+ // TODO: checks ajax call
+ // TODO: checks spinner
+ // TODO: remove item after restore
+ // TODO: bring back item if restore failed
+ });
+ });
+ describe('file previews', function() {
+ // TODO: check that preview URL is going through files_trashbin
+ });
+ describe('loading file list', function() {
+ // TODO: check that ajax URL is going through files_trashbin
+ });
+ describe('breadcrumbs', function() {
+ // TODO: test label + URL
+ });
+ describe('Global Actions', function() {
+ beforeEach(function() {
+ fileList.setFiles(testFiles);
+ fileList.findFileEl('One.txt.d11111').find('input:checkbox').click();
+ fileList.findFileEl('Three.pdf.d33333').find('input:checkbox').click();
+ fileList.findFileEl('somedir.d99999').find('input:checkbox').click();
+ });
+ describe('Delete', function() {
+ it('Deletes selected files when "Delete" clicked', function() {
+ var request;
+ $('.selectedActions .delete-selected').click();
+ expect(fakeServer.requests.length).toEqual(1);
+ request = fakeServer.requests[0];
+ expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_trashbin/ajax/delete.php');
+ expect(OC.parseQueryString(request.requestBody))
+ .toEqual({'dir': '/', files: '["One.txt.d11111","Three.pdf.d33333","somedir.d99999"]'});
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({
+ status: 'success',
+ data: {
+ success: [
+ {filename: 'One.txt.d11111'},
+ {filename: 'Three.pdf.d33333'},
+ {filename: 'somedir.d99999'}
+ ]
+ }
+ })
+ );
+ expect(fileList.findFileEl('One.txt.d11111').length).toEqual(0);
+ expect(fileList.findFileEl('Three.pdf.d33333').length).toEqual(0);
+ expect(fileList.findFileEl('somedir.d99999').length).toEqual(0);
+ expect(fileList.findFileEl('Two.jpg.d22222').length).toEqual(1);
+ });
+ it('Deletes all files when all selected when "Delete" clicked', function() {
+ var request;
+ $('.select-all').click();
+ $('.selectedActions .delete-selected').click();
+ expect(fakeServer.requests.length).toEqual(1);
+ request = fakeServer.requests[0];
+ expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_trashbin/ajax/delete.php');
+ expect(OC.parseQueryString(request.requestBody))
+ .toEqual({'dir': '/', allfiles: 'true'});
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({status: 'success'})
+ );
+ expect(fileList.isEmpty).toEqual(true);
+ });
+ });
+ describe('Restore', function() {
+ it('Restores selected files when "Restore" clicked', function() {
+ var request;
+ $('.selectedActions .undelete').click();
+ expect(fakeServer.requests.length).toEqual(1);
+ request = fakeServer.requests[0];
+ expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_trashbin/ajax/undelete.php');
+ expect(OC.parseQueryString(request.requestBody))
+ .toEqual({'dir': '/', files: '["One.txt.d11111","Three.pdf.d33333","somedir.d99999"]'});
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({
+ status: 'success',
+ data: {
+ success: [
+ {filename: 'One.txt.d11111'},
+ {filename: 'Three.pdf.d33333'},
+ {filename: 'somedir.d99999'}
+ ]
+ }
+ })
+ );
+ expect(fileList.findFileEl('One.txt.d11111').length).toEqual(0);
+ expect(fileList.findFileEl('Three.pdf.d33333').length).toEqual(0);
+ expect(fileList.findFileEl('somedir.d99999').length).toEqual(0);
+ expect(fileList.findFileEl('Two.jpg.d22222').length).toEqual(1);
+ });
+ it('Restores all files when all selected when "Restore" clicked', function() {
+ var request;
+ $('.select-all').click();
+ $('.selectedActions .undelete').click();
+ expect(fakeServer.requests.length).toEqual(1);
+ request = fakeServer.requests[0];
+ expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_trashbin/ajax/undelete.php');
+ expect(OC.parseQueryString(request.requestBody))
+ .toEqual({'dir': '/', allfiles: 'true'});
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({status: 'success'})
+ );
+ expect(fileList.isEmpty).toEqual(true);
+ });
+ });
+ });
+});