diff options
author | Roeland Jago Douma <roeland@famdouma.nl> | 2019-02-11 11:27:51 +0100 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2019-02-13 09:46:29 +0100 |
commit | 58ecc7d000e682df51c14562f369900dcd0f1eec (patch) | |
tree | df0c23636f6c33fe80d988ea5b83129f2d6d1d9c /apps/files_trashbin/src | |
parent | eab46d1ab151d87f8ddbe50b8719f22c7e5ec765 (diff) | |
download | nextcloud-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.js | 137 | ||||
-rw-r--r-- | apps/files_trashbin/src/filelist.js | 321 | ||||
-rw-r--r-- | apps/files_trashbin/src/files_trashbin.js | 5 | ||||
-rw-r--r-- | apps/files_trashbin/src/trash.scss | 22 |
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; +} + |