diff --git a/apps/reader/models.py b/apps/reader/models.py index 76a4a7582..4f2f25dcc 100644 --- a/apps/reader/models.py +++ b/apps/reader/models.py @@ -357,8 +357,6 @@ class UserSubscriptionFolders(models.Model): new_folders = [] for k, folder in enumerate(old_folders): if isinstance(folder, int): - if folder == 1128: - print folder_name, feed_id, type(feed_id), folder == feed_id, folder_name == in_folder, deleted if (folder == feed_id and ( (folder_name != in_folder) or (folder_name == in_folder and deleted))): @@ -398,8 +396,8 @@ class UserSubscriptionFolders(models.Model): user_sub.delete() MUserStory.objects(user_id=self.user.pk, feed_id=feed_id).delete() - def delete_folder(self, folder_to_delete, in_folder, feed_ids_in_folder): - def _find_folder_in_folders(old_folders, folder_name, feeds_to_delete): + def delete_folder(self, folder_to_delete, in_folder, feed_ids_in_folder, commit_delete=True): + def _find_folder_in_folders(old_folders, folder_name, feeds_to_delete, deleted_folder=None): new_folders = [] for k, folder in enumerate(old_folders): if isinstance(folder, int): @@ -410,18 +408,22 @@ class UserSubscriptionFolders(models.Model): for f_k, f_v in folder.items(): if f_k == folder_to_delete and folder_name == in_folder: logging.user(self.user, "~FBDeleting folder '~SB%s~SN' in '%s': %s" % (f_k, folder_name, folder)) + deleted_folder = folder else: - nf, feeds_to_delete = _find_folder_in_folders(f_v, f_k, feeds_to_delete) + nf, feeds_to_delete, deleted_folder = _find_folder_in_folders(f_v, f_k, feeds_to_delete, deleted_folder) new_folders.append({f_k: nf}) - return new_folders, feeds_to_delete + return new_folders, feeds_to_delete, deleted_folder user_sub_folders = json.decode(self.folders) - user_sub_folders, feeds_to_delete = _find_folder_in_folders(user_sub_folders, '', feed_ids_in_folder) + user_sub_folders, feeds_to_delete, deleted_folder = _find_folder_in_folders(user_sub_folders, '', feed_ids_in_folder) self.folders = json.encode(user_sub_folders) self.save() - UserSubscription.objects.filter(user=self.user, feed__in=feeds_to_delete).delete() + if commit_delete: + UserSubscription.objects.filter(user=self.user, feed__in=feeds_to_delete).delete() + + return deleted_folder def rename_folder(self, folder_to_rename, new_folder_name, in_folder): def _find_folder_in_folders(old_folders, folder_name): @@ -446,7 +448,6 @@ class UserSubscriptionFolders(models.Model): self.save() def move_feed_to_folder(self, feed_id, in_folder=None, to_folder=None): - print "%s: %s %s" % (feed_id, in_folder, to_folder) user_sub_folders = json.decode(self.folders) self.delete_feed(feed_id, in_folder, commit_delete=False) user_sub_folders = json.decode(self.folders) @@ -455,6 +456,16 @@ class UserSubscriptionFolders(models.Model): self.save() return self + + def move_folder_to_folder(self, folder_name, in_folder=None, to_folder=None): + user_sub_folders = json.decode(self.folders) + deleted_folder = self.delete_folder(folder_name, in_folder, [], commit_delete=False) + user_sub_folders = json.decode(self.folders) + user_sub_folders = add_object_to_folder(deleted_folder, to_folder, user_sub_folders) + self.folders = json.encode(user_sub_folders) + self.save() + + return self class Feature(models.Model): diff --git a/apps/reader/urls.py b/apps/reader/urls.py index af53f8c38..a750440d1 100644 --- a/apps/reader/urls.py +++ b/apps/reader/urls.py @@ -28,6 +28,7 @@ urlpatterns = patterns('', url(r'^rename_feed', views.rename_feed, name='rename-feed'), url(r'^rename_folder', views.rename_folder, name='rename-folder'), url(r'^move_feed_to_folder', views.move_feed_to_folder, name='move-feed-to-folder'), + url(r'^move_folder_to_folder', views.move_folder_to_folder, name='move-folder-to-folder'), url(r'^add_url', views.add_url), url(r'^add_folder', views.add_folder), url(r'^add_feature', views.add_feature, name='add-feature'), diff --git a/apps/reader/views.py b/apps/reader/views.py index 320182bf2..627fad3d2 100644 --- a/apps/reader/views.py +++ b/apps/reader/views.py @@ -865,6 +865,18 @@ def move_feed_to_folder(request): return dict(code=1, folders=json.decode(user_sub_folders.folders)) +@ajax_login_required +@json.json_view +def move_folder_to_folder(request): + folder_name = request.POST['folder_name'] + in_folder = request.POST.get('in_folder', '') + to_folder = request.POST.get('to_folder', '') + + user_sub_folders = get_object_or_404(UserSubscriptionFolders, user=request.user) + user_sub_folders = user_sub_folders.move_folder_to_folder(folder_name, in_folder=in_folder, to_folder=to_folder) + + return dict(code=1, folders=json.decode(user_sub_folders.folders)) + @login_required def add_feature(request): if not request.user.is_staff: diff --git a/media/js/newsblur/assetmodel.js b/media/js/newsblur/assetmodel.js index 40629cd3e..c661dff7e 100644 --- a/media/js/newsblur/assetmodel.js +++ b/media/js/newsblur/assetmodel.js @@ -680,6 +680,19 @@ NEWSBLUR.AssetModel.Reader.prototype = { }, pre_callback); }, + move_folder_to_folder: function(folder_name, in_folder, to_folder, callback) { + var pre_callback = _.bind(function(data) { + this.folders = data.folders; + return callback(); + }, this); + + this.make_request('/reader/move_folder_to_folder', { + 'folder_name': folder_name, + 'in_folder': in_folder, + 'to_folder': to_folder + }, pre_callback); + }, + preference: function(preference, value, callback) { if (typeof value == 'undefined') { var pref = NEWSBLUR.Preferences[preference]; diff --git a/media/js/newsblur/reader.js b/media/js/newsblur/reader.js index 3547f9168..81eaa139a 100644 --- a/media/js/newsblur/reader.js +++ b/media/js/newsblur/reader.js @@ -4644,16 +4644,24 @@ manage_menu_move_folder: function(folder, $folder) { var self = this; var in_folder = ''; - var $parent = $folder.closest('li.folder'); - var new_folder = $('.NB-menu-manage-folder-move-confirm select').val(); - + var $parent = $folder.parents('li.folder').eq(0); + var to_folder = $('.NB-menu-manage-folder-move-confirm select').val(); + var folder_name = $folder.find('.folder_title_text').eq(0).text(); + var child_folders = $folder.find('.folder_title_text').map(function() { + return $(this).text(); + }).get(); + if ($parent.length) { in_folder = $parent.find('.folder_title_text').eq(0).text(); } - if (new_folder == in_folder) return this.hide_confirm_move_menu_item(); + if (to_folder == in_folder || + to_folder == folder_name || + _.contains(child_folders, to_folder)) { + return this.hide_confirm_move_menu_item(); + } - this.model.move_folder_to_folder(folder, new_folder, in_folder, function() { + this.model.move_folder_to_folder(folder, in_folder, to_folder, _.bind(function() { _.delay(_.bind(function() { this.$s.$feed_list.css('opacity', 1).animate({'opacity': 0}, { 'duration': 100, @@ -4662,8 +4670,10 @@ }, this) }); }, this), 250); - this.hide_manage_menu('folder', $folder, true); - }); + + this.hide_manage_menu('folder', $parent, true); + }, this)); + this.hide_confirm_move_menu_item(true); }, diff --git a/templates/static/api.yml b/templates/static/api.yml index 6e04f7c46..d2bb44bb0 100644 --- a/templates/static/api.yml +++ b/templates/static/api.yml @@ -270,17 +270,17 @@ - url: /reader/mark_feed_as_read method: POST - short_desc: "Mark all stories in a feed as read." + short_desc: "Mark a list of feeds as read." long_desc: - - "Mark all stories in a feed or list of feeds as read." + - "Mark a list of feeds as read." + params: + - key: feed_id + desc: "List of feed ids to mark as read." + required: true + example: "[12, 24, 36]" tips: - "To mark a folder as read, send the ids of each feed inside the folder." - params: - - key: feed_ids - desc: "List of feed ids to mark as read." - optional: true - example: "[12, 24, 36]" - + - url: /reader/mark_all_as_read method: POST short_desc: "Mark all stories from all feeds as read." @@ -328,6 +328,52 @@ default: "[Top Level]" example: "All Blogs" + - url: /reader/move_feed_to_folder + method: POST + short_desc: "Move a feed into a different folder." + long_desc: + - "Move a feed into a different folder." + params: + - key: feed_id + desc: "Feed id." + required: true + example: 12 + - key: in_folder + desc: > + Current folder the feed is in. Necessary to disambiguate if a feed is in + multiple folders. + required: true + example: "Blogs" + - key: in_folder + desc: "Folder the feed is going into." + required: true + example: "Tumblrs" + tips: + - "Leave folder names blank to specify Top Level." + + - url: /reader/move_folder_to_folder + method: POST + short_desc: "Move a folder into a different folder." + long_desc: + - "Move a folder into a different folder." + params: + - key: folder_name + desc: "Name of folder being moved." + required: true + example: "Tumblrs" + - key: in_folder + desc: > + Current folder the folder is in. Necessary to disambiguate if a folder + name is in multiple folders. (Please don't let this happen.) + required: true + example: "Blogs" + - key: in_folder + desc: "New folder the existing folder is going into." + required: true + example: "Daily Blogs" + tips: + - "Leave folder names blank to specify Top Level." + - url: /reader/rename_feed method: POST short_desc: "Rename a feed title." @@ -399,17 +445,7 @@ desc: "List of feed ids in the folder that's being deleted. These feeds also get removed." optional: true example: "[12, 24, 36]" - - - url: /reader/mark_feed_as_read - method: POST - short_desc: "Mark a list of feeds as read." - long_desc: - - "Mark a list of feeds as read." - params: - - key: feed_id - desc: "List of feed ids to mark as read." - required: true - example: "[12, 24, 36]" + - url: /reader/save_feed_order method: POST