summaryrefslogtreecommitdiffstats
path: root/apps/files_trashbin/src
diff options
context:
space:
mode:
authorRoeland Jago Douma <roeland@famdouma.nl>2019-02-11 11:27:51 +0100
committerRoeland Jago Douma <roeland@famdouma.nl>2019-02-13 09:46:29 +0100
commit58ecc7d000e682df51c14562f369900dcd0f1eec (patch)
treedf0c23636f6c33fe80d988ea5b83129f2d6d1d9c /apps/files_trashbin/src
parenteab46d1ab151d87f8ddbe50b8719f22c7e5ec765 (diff)
downloadnextcloud-server-58ecc7d000e682df51c14562f369900dcd0f1eec.tar.gz
nextcloud-server-58ecc7d000e682df51c14562f369900dcd0f1eec.zip
Move files_trashbin to webpack
Combine the 2 js files and the scss. This saves compiling the scss on the go. And going via Nextcloud storage to obtain it. Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'apps/files_trashbin/src')
-rw-r--r--apps/files_trashbin/src/app.js137
-rw-r--r--apps/files_trashbin/src/filelist.js321
-rw-r--r--apps/files_trashbin/src/files_trashbin.js5
-rw-r--r--apps/files_trashbin/src/trash.scss22
4 files changed, 485 insertions, 0 deletions
diff --git a/apps/files_trashbin/src/app.js b/apps/files_trashbin/src/app.js
new file mode 100644
index 00000000000..199cb7d4f84
--- /dev/null
+++ b/apps/files_trashbin/src/app.js
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+/**
+ * @namespace OCA.Trashbin
+ */
+OCA.Trashbin = {};
+/**
+ * @namespace OCA.Trashbin.App
+ */
+OCA.Trashbin.App = {
+ _initialized: false,
+ /** @type {OC.Files.Client} */
+ client: null,
+
+ initialize: function ($el) {
+ if (this._initialized) {
+ return;
+ }
+ this._initialized = true;
+
+ this.client = new OC.Files.Client({
+ host: OC.getHost(),
+ port: OC.getPort(),
+ root: OC.linkToRemoteBase('dav') + '/trashbin/' + OC.getCurrentUser().uid,
+ useHTTPS: OC.getProtocol() === 'https'
+ });
+ var urlParams = OC.Util.History.parseUrlQuery();
+ this.fileList = new OCA.Trashbin.FileList(
+ $('#app-content-trashbin'), {
+ fileActions: this._createFileActions(),
+ detailsViewEnabled: false,
+ scrollTo: urlParams.scrollto,
+ config: OCA.Files.App.getFilesConfig(),
+ multiSelectMenu: [
+ {
+ name: 'restore',
+ displayName: t('files', 'Restore'),
+ iconClass: 'icon-history',
+ },
+ {
+ name: 'delete',
+ displayName: t('files', 'Delete'),
+ iconClass: 'icon-delete',
+ }
+ ],
+ client: this.client,
+ // The file list is created when a "show" event is handled, so
+ // it should be marked as "shown" like it would have been done
+ // if handling the event with the file list already created.
+ shown: true
+ }
+ );
+ },
+
+ _createFileActions: function () {
+ var client = this.client;
+ var fileActions = new OCA.Files.FileActions();
+ fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) {
+ var dir = context.fileList.getCurrentDirectory();
+ context.fileList.changeDirectory(OC.joinPaths(dir, filename));
+ });
+
+ fileActions.setDefault('dir', 'Open');
+
+ fileActions.registerAction({
+ name: 'Restore',
+ displayName: t('files_trashbin', 'Restore'),
+ type: OCA.Files.FileActions.TYPE_INLINE,
+ mime: 'all',
+ permissions: OC.PERMISSION_READ,
+ iconClass: 'icon-history',
+ actionHandler: function (filename, context) {
+ var fileList = context.fileList;
+ var tr = fileList.findFileEl(filename);
+ fileList.showFileBusyState(tr, true);
+ var dir = context.fileList.getCurrentDirectory();
+ client.move(OC.joinPaths('trash', dir, filename), OC.joinPaths('restore', filename), true)
+ .then(
+ fileList._removeCallback.bind(fileList, [filename]),
+ function () {
+ fileList.showFileBusyState(tr, false);
+ OC.Notification.show(t('files_trashbin', 'Error while restoring file from trashbin'));
+ }
+ );
+ }
+ });
+
+ fileActions.registerAction({
+ name: 'Delete',
+ displayName: t('files', 'Delete'),
+ mime: 'all',
+ permissions: OC.PERMISSION_READ,
+ iconClass: 'icon-delete',
+ render: function (actionSpec, isDefault, context) {
+ var $actionLink = fileActions._makeActionLink(actionSpec, context);
+ $actionLink.attr('original-title', t('files_trashbin', 'Delete permanently'));
+ $actionLink.children('img').attr('alt', t('files_trashbin', 'Delete permanently'));
+ context.$file.find('td:last').append($actionLink);
+ return $actionLink;
+ },
+ actionHandler: function (filename, context) {
+ var fileList = context.fileList;
+ $('.tipsy').remove();
+ var tr = fileList.findFileEl(filename);
+ fileList.showFileBusyState(tr, true);
+ var dir = context.fileList.getCurrentDirectory();
+ client.remove(OC.joinPaths('trash', dir, filename))
+ .then(
+ fileList._removeCallback.bind(fileList, [filename]),
+ function () {
+ fileList.showFileBusyState(tr, false);
+ OC.Notification.show(t('files_trashbin', 'Error while removing file from trashbin'));
+ }
+ );
+ }
+ });
+ return 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/src/filelist.js b/apps/files_trashbin/src/filelist.js
new file mode 100644
index 00000000000..07e041faefd
--- /dev/null
+++ b/apps/files_trashbin/src/filelist.js
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+(function() {
+ var DELETED_REGEXP = new RegExp(/^(.+)\.d[0-9]+$/);
+ var FILENAME_PROP = '{http://nextcloud.org/ns}trashbin-filename';
+ var DELETION_TIME_PROP = '{http://nextcloud.org/ns}trashbin-deletion-time';
+ var TRASHBIN_ORIGINAL_LOCATION = '{http://nextcloud.org/ns}trashbin-original-location';
+
+ /**
+ * 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 {String} name file name
+ * @return {String} converted file name
+ */
+ function getDeletedFileName(name) {
+ name = OC.basename(name);
+ var match = DELETED_REGEXP.exec(name);
+ if (match && match.length > 1) {
+ name = match[1];
+ }
+ return name;
+ }
+
+ /**
+ * @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
+ */
+ var FileList = function($el, options) {
+ this.client = options.client;
+ this.initialize($el, options);
+ };
+ FileList.prototype = _.extend({}, OCA.Files.FileList.prototype,
+ /** @lends OCA.Trashbin.FileList.prototype */ {
+ id: 'trashbin',
+ appName: t('files_trashbin', 'Deleted files'),
+ /** @type {OC.Files.Client} */
+ client: null,
+
+ /**
+ * @private
+ */
+ initialize: function() {
+ this.client.addFileInfoParser(function(response, data) {
+ var props = response.propStat[0].properties;
+ var path = props[TRASHBIN_ORIGINAL_LOCATION];
+ return {
+ displayName: props[FILENAME_PROP],
+ mtime: parseInt(props[DELETION_TIME_PROP], 10) * 1000,
+ hasPreview: true,
+ path: path,
+ extraData: path
+ }
+ });
+
+ var result = OCA.Files.FileList.prototype.initialize.apply(this, arguments);
+ this.$el.find('.undelete').click('click', _.bind(this._onClickRestoreSelected, this));
+
+ 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;
+ };
+
+ OC.Plugins.attach('OCA.Trashbin.FileList', this);
+ return result;
+ },
+
+ /**
+ * Override to only return read permissions
+ */
+ getDirectoryPermissions: function() {
+ return OC.PERMISSION_READ | OC.PERMISSION_DELETE;
+ },
+
+ _setCurrentDir: function(targetDir) {
+ OCA.Files.FileList.prototype._setCurrentDir.apply(this, arguments);
+
+ 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;
+ },
+
+ getAjaxUrl: function(action, params) {
+ var q = '';
+ if (params) {
+ q = '?' + OC.buildQueryString(params);
+ }
+ return OC.filePath('files_trashbin', 'ajax', action + '.php') + q;
+ },
+
+ setupUploadEvents: function() {
+ // override and do nothing
+ },
+
+ linkTo: function(dir){
+ return OC.linkTo('files', 'index.php')+"?view=trashbin&dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
+ },
+
+ 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;
+ },
+
+ 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(files) {
+ var $el;
+ for (var i = 0; i < files.length; i++) {
+ $el = this.remove(OC.basename(files[i]), {updateSummary: false});
+ this.fileSummary.remove({type: $el.attr('data-type'), size: $el.attr('data-size')});
+ }
+ this.fileSummary.update();
+ this.updateEmptyContent();
+ },
+
+ _onClickRestoreSelected: function(event) {
+ event.preventDefault();
+ var self = this;
+ var files = _.pluck(this.getSelectedFiles(), 'name');
+ for (var i = 0; i < files.length; i++) {
+ var tr = this.findFileEl(files[i]);
+ this.showFileBusyState(tr, true);
+ }
+
+ this.fileMultiSelectMenu.toggleLoading('restore', true);
+ var restorePromises = files.map(function(file) {
+ return self.client.move(OC.joinPaths('trash', self.getCurrentDirectory(), file), OC.joinPaths('restore', file), true)
+ .then(
+ function() {
+ self._removeCallback([file]);
+ }
+ );
+ });
+ return Promise.all(restorePromises).then(
+ function() {
+ self.fileMultiSelectMenu.toggleLoading('restore', false);
+ },
+ function() {
+ OC.Notification.show(t('files_trashbin', 'Error while restoring files from trashbin'));
+ }
+ );
+ },
+
+ _onClickDeleteSelected: function(event) {
+ event.preventDefault();
+ var self = this;
+ var allFiles = this.$el.find('.select-all').is(':checked');
+ var files = _.pluck(this.getSelectedFiles(), 'name');
+ for (var i = 0; i < files.length; i++) {
+ var tr = this.findFileEl(files[i]);
+ this.showFileBusyState(tr, true);
+ }
+
+ if (allFiles) {
+ return this.client.remove(OC.joinPaths('trash', this.getCurrentDirectory()))
+ .then(
+ function() {
+ self.hideMask();
+ self.setFiles([]);
+ },
+ function() {
+ OC.Notification.show(t('files_trashbin', 'Error while emptying trashbin'));
+ }
+ );
+ } else {
+ this.fileMultiSelectMenu.toggleLoading('delete', true);
+ var deletePromises = files.map(function(file) {
+ return self.client.remove(OC.joinPaths('trash', self.getCurrentDirectory(), file))
+ .then(
+ function() {
+ self._removeCallback([file]);
+ }
+ );
+ });
+ return Promise.all(deletePromises).then(
+ function() {
+ self.fileMultiSelectMenu.toggleLoading('delete', false);
+ },
+ function() {
+ OC.Notification.show(t('files_trashbin', 'Error while removing files from trashbin'));
+ }
+ );
+ }
+ },
+
+ _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/preview?') + $.param(urlSpec);
+ },
+
+ getDownloadUrl: function() {
+ // no downloads
+ return '#';
+ },
+
+ updateStorageStatistics: function() {
+ // no op because the trashbin doesn't have
+ // storage info like free space / used space
+ },
+
+ isSelectedDeletable: function() {
+ return true;
+ },
+
+ /**
+ * Returns list of webdav properties to request
+ */
+ _getWebdavProperties: function() {
+ return [FILENAME_PROP, DELETION_TIME_PROP, TRASHBIN_ORIGINAL_LOCATION].concat(this.filesClient.getPropfindProperties());
+ },
+
+ /**
+ * 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 = this.client.getFolderContents(
+ 'trash/' + this.getCurrentDirectory(), {
+ includeParent: false,
+ properties: this._getWebdavProperties()
+ }
+ );
+ var callBack = this.reloadCallback.bind(this);
+ return this._reloadCall.then(callBack, callBack);
+ },
+ reloadCallback: function(status, result) {
+ delete this._reloadCall;
+ this.hideMask();
+
+ if (status === 401) {
+ return false;
+ }
+
+ // Firewall Blocked request?
+ if (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 (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 (status === 404) {
+ // go back home
+ this.changeDirectory('/');
+ return false;
+ }
+ // aborted ?
+ if (status === 0){
+ return true;
+ }
+
+ this.setFiles(result);
+ return true;
+ },
+
+ });
+
+ OCA.Trashbin.FileList = FileList;
+})();
+
diff --git a/apps/files_trashbin/src/files_trashbin.js b/apps/files_trashbin/src/files_trashbin.js
new file mode 100644
index 00000000000..59f93e8ee26
--- /dev/null
+++ b/apps/files_trashbin/src/files_trashbin.js
@@ -0,0 +1,5 @@
+import './app'
+import './filelist'
+import './trash.scss'
+
+window.OCA.Trashbin = OCA.Trashbin
diff --git a/apps/files_trashbin/src/trash.scss b/apps/files_trashbin/src/trash.scss
new file mode 100644
index 00000000000..2ed57b51918
--- /dev/null
+++ b/apps/files_trashbin/src/trash.scss
@@ -0,0 +1,22 @@
+/*
+ * 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.nametext,
+#app-content-trashbin tbody tr[data-type="file"] td a.name span.nametext span {
+ cursor: default;
+}
+
+#app-content-trashbin .summary :last-child {
+ padding: 0;
+}
+#app-content-trashbin #filestable .summary .filesize {
+ display: none;
+}
+