summaryrefslogtreecommitdiffstats
path: root/apps/files/js
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2014-11-18 18:53:45 +0100
committerVincent Petry <pvince81@owncloud.com>2014-12-15 12:10:54 +0100
commita5bb66f4a723bce5c5fbe919a48cd5133204ef62 (patch)
treeb2e067bde8aaa1de6973adc7760fafb1e37e9084 /apps/files/js
parentc6be491a89a4eebe15bcb20f6e0b01f23a093761 (diff)
downloadnextcloud-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.js2
-rw-r--r--apps/files/js/favoritesfilelist.js99
-rw-r--r--apps/files/js/favoritesplugin.js116
-rw-r--r--apps/files/js/tagsplugin.js135
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 ? '&#x2605' : '&#x2606;';
+ 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 ? '&#x2606;' : '&#x2605;');
+ $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);
+