diff options
author | Vincent Petry <pvince81@owncloud.com> | 2014-11-18 18:53:45 +0100 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2014-12-15 12:10:54 +0100 |
commit | a5bb66f4a723bce5c5fbe919a48cd5133204ef62 (patch) | |
tree | b2e067bde8aaa1de6973adc7760fafb1e37e9084 /apps/files/js | |
parent | c6be491a89a4eebe15bcb20f6e0b01f23a093761 (diff) | |
download | nextcloud-server-a5bb66f4a723bce5c5fbe919a48cd5133204ef62.tar.gz nextcloud-server-a5bb66f4a723bce5c5fbe919a48cd5133204ef62.zip |
Added favorites feature to the files app
Diffstat (limited to 'apps/files/js')
-rw-r--r-- | apps/files/js/app.js | 2 | ||||
-rw-r--r-- | apps/files/js/favoritesfilelist.js | 99 | ||||
-rw-r--r-- | apps/files/js/favoritesplugin.js | 116 | ||||
-rw-r--r-- | apps/files/js/tagsplugin.js | 135 |
4 files changed, 352 insertions, 0 deletions
diff --git a/apps/files/js/app.js b/apps/files/js/app.js index ee5330485e7..adb1893bb0e 100644 --- a/apps/files/js/app.js +++ b/apps/files/js/app.js @@ -80,6 +80,8 @@ // refer to the one of the "files" view window.FileList = this.fileList; + OC.Plugins.attach('OCA.Files.App', this); + this._setupEvents(); // trigger URL change event handlers this._onPopState(urlParams); diff --git a/apps/files/js/favoritesfilelist.js b/apps/files/js/favoritesfilelist.js new file mode 100644 index 00000000000..0d555ce609d --- /dev/null +++ b/apps/files/js/favoritesfilelist.js @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +// HACK: this piece needs to be loaded AFTER the files app (for unit tests) +$(document).ready(function() { + (function(OCA) { + /** + * @class OCA.Files.FavoritesFileList + * @augments OCA.Files.FavoritesFileList + * + * @classdesc Favorites file list. + * Displays the list of files marked as favorites + * + * @param $el container element with existing markup for the #controls + * and a table + * @param [options] map of options, see other parameters + */ + var FavoritesFileList = function($el, options) { + this.initialize($el, options); + }; + FavoritesFileList.prototype = _.extend({}, OCA.Files.FileList.prototype, + /** @lends OCA.Files.FavoritesFileList.prototype */ { + id: 'favorites', + appName: 'Favorites', + + _clientSideSort: true, + _allowSelection: false, + + /** + * @private + */ + initialize: function($el, options) { + OCA.Files.FileList.prototype.initialize.apply(this, arguments); + if (this.initialized) { + return; + } + OC.Plugins.attach('OCA.Files.FavoritesFileList', this); + }, + + updateEmptyContent: function() { + var dir = this.getCurrentDirectory(); + if (dir === '/') { + // root has special permissions + this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty); + this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty); + } + else { + OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments); + } + }, + + getDirectoryPermissions: function() { + return OC.PERMISSION_READ | OC.PERMISSION_DELETE; + }, + + updateStorageStatistics: function() { + // no op because it doesn't have + // storage info like free space / used space + }, + + reload: function() { + var tagName = OC.TAG_FAVORITE; + this.showMask(); + if (this._reloadCall) { + this._reloadCall.abort(); + } + this._reloadCall = $.ajax({ + url: OC.generateUrl('/apps/files/api/v1/tags/{tagName}/files', {tagName: tagName}), + type: 'GET', + dataType: 'json' + }); + var callBack = this.reloadCallback.bind(this); + return this._reloadCall.then(callBack, callBack); + }, + + reloadCallback: function(result) { + delete this._reloadCall; + this.hideMask(); + + if (result.files) { + this.setFiles(result.files.sort(this._sortComparator)); + } + else { + // TODO: error handling + } + } + }); + + OCA.Files.FavoritesFileList = FavoritesFileList; + })(OCA); +}); + diff --git a/apps/files/js/favoritesplugin.js b/apps/files/js/favoritesplugin.js new file mode 100644 index 00000000000..417a32ef804 --- /dev/null +++ b/apps/files/js/favoritesplugin.js @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +(function(OCA) { + /** + * @namespace OCA.Files.FavoritesPlugin + * + * Registers the favorites file list from the files app sidebar. + */ + OCA.Files.FavoritesPlugin = { + name: 'Favorites', + + /** + * @type OCA.Files.FavoritesFileList + */ + favoritesFileList: null, + + attach: function() { + var self = this; + $('#app-content-favorites').on('show.plugin-favorites', function(e) { + self.showFileList($(e.target)); + }); + $('#app-content-favorites').on('hide.plugin-favorites', function() { + self.hideFileList(); + }); + }, + + detach: function() { + if (this.favoritesFileList) { + this.favoritesFileList.destroy(); + OCA.Files.fileActions.off('setDefault.plugin-favorites', this._onActionsUpdated); + OCA.Files.fileActions.off('registerAction.plugin-favorites', this._onActionsUpdated); + $('#app-content-favorites').off('.plugin-favorites'); + this.favoritesFileList = null; + } + }, + + showFileList: function($el) { + if (!this.favoritesFileList) { + this.favoritesFileList = this._createFavoritesFileList($el); + } + return this.favoritesFileList; + }, + + hideFileList: function() { + if (this.favoritesFileList) { + this.favoritesFileList.$fileList.empty(); + } + }, + + /** + * Creates the favorites file list. + * + * @param $el container for the file list + * @return {OCA.Files.FavoritesFileList} file list + */ + _createFavoritesFileList: function($el) { + var fileActions = this._createFileActions(); + // register favorite list for sidebar section + return new OCA.Files.FavoritesFileList( + $el, { + fileActions: fileActions, + scrollContainer: $('#app-content') + } + ); + }, + + _createFileActions: function() { + // inherit file actions from the files app + var fileActions = new OCA.Files.FileActions(); + // note: not merging the legacy actions because legacy apps are not + // compatible with the sharing overview and need to be adapted first + fileActions.registerDefaultActions(); + fileActions.merge(OCA.Files.fileActions); + + if (!this._globalActionsInitialized) { + // in case actions are registered later + this._onActionsUpdated = _.bind(this._onActionsUpdated, this); + OCA.Files.fileActions.on('setDefault.plugin-favorites', this._onActionsUpdated); + OCA.Files.fileActions.on('registerAction.plugin-favorites', this._onActionsUpdated); + this._globalActionsInitialized = true; + } + + // when the user clicks on a folder, redirect to the corresponding + // folder in the files app instead of opening it directly + fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) { + OCA.Files.App.setActiveView('files', {silent: true}); + OCA.Files.App.fileList.changeDirectory(context.$file.attr('data-path') + '/' + filename, true, true); + }); + fileActions.setDefault('dir', 'Open'); + return fileActions; + }, + + _onActionsUpdated: function(ev) { + if (ev.action) { + this.favoritesFileList.fileActions.registerAction(ev.action); + } else if (ev.defaultAction) { + this.favoritesFileList.fileActions.setDefault( + ev.defaultAction.mime, + ev.defaultAction.name + ); + } + } + }; + +})(OCA); + +OC.Plugins.register('OCA.Files.App', OCA.Files.FavoritesPlugin); + diff --git a/apps/files/js/tagsplugin.js b/apps/files/js/tagsplugin.js new file mode 100644 index 00000000000..77b3167ab5e --- /dev/null +++ b/apps/files/js/tagsplugin.js @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ +(function(OCA) { + + OCA.Files = OCA.Files || {}; + + /** + * @namespace OCA.Files.TagsPlugin + * + * Extends the file actions and file list to include a favorite action icon + * and addition "data-tags" and "data-favorite" attributes. + */ + OCA.Files.TagsPlugin = { + name: 'Tags', + + allowedLists: [ + 'files', + 'favorites' + ], + + _extendFileActions: function(fileActions) { + var self = this; + // register "star" action + fileActions.registerAction({ + name: 'favorite', + displayName: 'Favorite', + mime: 'all', + permissions: OC.PERMISSION_READ, + render: function(actionSpec, isDefault, context) { + // TODO: use proper icon + var $file = context.$file; + var isFavorite = $file.data('favorite') === true; + var starState = isFavorite ? '★' : '☆'; + var $icon = $( + '<a href="#" class="action action-favorite ' + (isFavorite ? 'permanent' : '') + '">' + + starState + '</a>' + ); + $file.find('td:first>.favorite').prepend($icon); + return $icon; + }, + actionHandler: function(fileName, context) { + var $actionEl = context.$file.find('.action-favorite'); + var $file = context.$file; + var dir = context.dir || context.fileList.getCurrentDirectory(); + var tags = $file.attr('data-tags'); + if (_.isUndefined(tags)) { + tags = ''; + } + tags = tags.split('|'); + tags = _.without(tags, ''); + var isFavorite = tags.indexOf(OC.TAG_FAVORITE) >= 0; + if (isFavorite) { + // remove tag from list + tags = _.without(tags, OC.TAG_FAVORITE); + } else { + tags.push(OC.TAG_FAVORITE); + } + if ($actionEl.hasClass('icon-loading')) { + // do nothing + return; + } + $actionEl.addClass('icon-loading permanent'); + self.applyFileTags( + dir + '/' + fileName, + tags + ).then(function() { + // TODO: read from result + $actionEl.removeClass('icon-loading'); + $actionEl.html(isFavorite ? '☆' : '★'); + $actionEl.toggleClass('permanent', !isFavorite); + $file.attr('data-tags', tags.join('|')); + $file.attr('data-favorite', !isFavorite); + }); + } + }); + }, + + _extendFileList: function(fileList) { + // extend row prototype + fileList.$fileList.addClass('has-favorites'); + var oldCreateRow = fileList._createRow; + fileList._createRow = function(fileData) { + var $tr = oldCreateRow.apply(this, arguments); + if (fileData.tags) { + $tr.attr('data-tags', fileData.tags.join('|')); + if (fileData.tags.indexOf(OC.TAG_FAVORITE) >= 0) { + $tr.attr('data-favorite', true); + } + } + $tr.find('td:first').prepend('<div class="favorite"></div>'); + return $tr; + }; + }, + + attach: function(fileList) { + if (this.allowedLists.indexOf(fileList.id) < 0) { + return; + } + this._extendFileActions(fileList.fileActions); + this._extendFileList(fileList); + }, + + /** + * Replaces the given files' tags with the specified ones. + * + * @param {String} fileName path to the file or folder to tag + * @param {Array.<String>} tagNames array of tag names + */ + applyFileTags: function(fileName, tagNames) { + var encodedPath = OC.encodePath(fileName); + while (encodedPath[0] === '/') { + encodedPath = encodedPath.substr(1); + } + return $.ajax({ + url: OC.generateUrl('/apps/files/api/v1/files/') + encodedPath, + contentType: 'application/json', + data: JSON.stringify({ + tags: tagNames || [] + }), + dataType: 'json', + type: 'POST' + }); + } + }; +})(OCA); + +OC.Plugins.register('OCA.Files.FileList', OCA.Files.TagsPlugin); + |