diff --git a/app/assets/javascripts/discourse/lib/keyboard_shortcuts.js b/app/assets/javascripts/discourse/lib/keyboard_shortcuts.js
index 76ec7b4c904..893f34b98c3 100644
--- a/app/assets/javascripts/discourse/lib/keyboard_shortcuts.js
+++ b/app/assets/javascripts/discourse/lib/keyboard_shortcuts.js
@@ -17,7 +17,6 @@ var PATH_BINDINGS = {
},
CLICK_BINDINGS = {
- 'f': '#topic-footer-buttons button.bookmark', // bookmark topic
'm m': 'div.notification-options li[data-id="0"] a', // mark topic as muted
'm r': 'div.notification-options li[data-id="1"] a', // mark topic as regular
'm t': 'div.notification-options li[data-id="2"] a', // mark topic as tracking
@@ -50,7 +49,8 @@ var PATH_BINDINGS = {
'command+f': 'showBuiltinSearch',
'?': 'showHelpModal', // open keyboard shortcut help
'q': 'quoteReply',
- 'b': 'toggleBookmark'
+ 'b': 'toggleBookmark',
+ 'f': 'toggleBookmarkTopic'
};
@@ -70,6 +70,16 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
this.sendToTopicListItemView('toggleBookmark');
},
+ toggleBookmarkTopic: function(){
+ var topic = this.currentTopic();
+ // BIG hack, need a cleaner way
+ if(topic && $('.posts-wrapper').length > 0) {
+ topic.toggleBookmark();
+ } else {
+ this.sendToTopicListItemView('toggleBookmark');
+ }
+ },
+
quoteReply: function(){
$('.topic-post.selected button.create').click();
// lazy but should work for now
@@ -170,6 +180,16 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
}
},
+ currentTopic: function(){
+ var topicController = this.container.lookup('controller:topic');
+ if(topicController) {
+ var topic = topicController.get('model');
+ if(topic){
+ return topic;
+ }
+ }
+ },
+
sendToSelectedPost: function(action){
var container = this.container;
// TODO: We should keep track of the post without a CSS class
diff --git a/app/assets/javascripts/discourse/models/_post.js b/app/assets/javascripts/discourse/models/_post.js
index 7eeb44b25e2..4311bbbe0e1 100644
--- a/app/assets/javascripts/discourse/models/_post.js
+++ b/app/assets/javascripts/discourse/models/_post.js
@@ -413,15 +413,27 @@ Discourse.Post = Discourse.Model.extend({
},
toggleBookmark: function() {
- var self = this;
+ var self = this,
+ bookmarkedTopic;
this.toggleProperty("bookmarked");
- if (this.get("post_number") === 1) { this.toggleProperty("topic.bookmarked"); }
- return Discourse.Post.updateBookmark(this.get('id'), this.get('bookmarked')).catch(function() {
- self.toggleProperty("bookmarked");
- if (this.get("post_number") === 1) { this.toggleProperty("topic.bookmarked"); }
- });
+ if(this.get("bookmarked") && !this.get("topic.bookmarked")) {
+ this.set("topic.bookmarked", true);
+ bookmarkedTopic = true;
+ }
+
+ // need to wait to hear back from server (stuff may not be loaded)
+
+ return Discourse.Post.updateBookmark(this.get('id'), this.get('bookmarked'))
+ .then(function(result){
+ self.set("topic.bookmarked", result.topic_bookmarked);
+ })
+ .catch(function(e) {
+ self.toggleProperty("bookmarked");
+ if (bookmarkedTopic) {self.set("topic.bookmarked", false); }
+ throw e;
+ });
}
});
diff --git a/app/assets/javascripts/discourse/models/topic.js.es6 b/app/assets/javascripts/discourse/models/topic.js.es6
index c2a4d0517db..7dff779589f 100644
--- a/app/assets/javascripts/discourse/models/topic.js.es6
+++ b/app/assets/javascripts/discourse/models/topic.js.es6
@@ -183,18 +183,48 @@ const Topic = Discourse.Model.extend({
}.property('word_count'),
toggleBookmark() {
- const self = this, firstPost = this.get("postStream.posts")[0];
+ const self = this,
+ stream = this.get('postStream'),
+ posts = Em.get(stream, 'posts'),
+ firstPost = posts &&
+ posts[0] &&
+ posts[0].get('post_number') === 1 &&
+ posts[0],
+ bookmark = !self.get('bookmarked');
+
+ var path = bookmark ? '/bookmark' : '/remove_bookmarks';
+ var unbookmarkedPosts = [],
+ bookmarkedPost;
this.toggleProperty('bookmarked');
- if (this.get("postStream.firstPostPresent")) { firstPost.toggleProperty("bookmarked"); }
+ if (bookmark && firstPost) {
+ firstPost.set('bookmarked', true);
+ bookmarkedPost = firstPost;
+ }
- return Discourse.ajax('/t/' + this.get('id') + '/bookmark', {
+ if (!bookmark && posts) {
+ posts.forEach(function(post){
+ if(post.get('bookmarked')){
+ post.set('bookmarked', false);
+ unbookmarkedPosts.push(post);
+ }
+ });
+ }
+
+ return Discourse.ajax('/t/' + this.get('id') + path, {
type: 'PUT',
- data: { bookmarked: self.get('bookmarked') },
}).catch(function(error) {
+
self.toggleProperty('bookmarked');
- if (self.get("postStream.firstPostPresent")) { firstPost.toggleProperty('bookmarked'); }
+
+ if(bookmarkedPost) {
+ bookmarkedPost.set('bookmarked', false);
+ }
+
+ unbookmarkedPosts.forEach(function(p){
+ p.set('bookmarked', true);
+ });
let showGenericError = true;
if (error && error.responseText) {
@@ -207,6 +237,8 @@ const Topic = Discourse.Model.extend({
if(showGenericError){
bootbox.alert(I18n.t('generic_error'));
}
+
+ throw error;
});
},
diff --git a/app/assets/javascripts/discourse/views/bookmark-button.js.es6 b/app/assets/javascripts/discourse/views/bookmark-button.js.es6
index 2a9188d5732..c99f955c8c9 100644
--- a/app/assets/javascripts/discourse/views/bookmark-button.js.es6
+++ b/app/assets/javascripts/discourse/views/bookmark-button.js.es6
@@ -2,9 +2,12 @@ import ButtonView from 'discourse/views/button';
export default ButtonView.extend({
classNames: ['bookmark'],
- textKey: 'bookmarked.title',
attributeBindings: ['disabled'],
+ textKey: function() {
+ return this.get('controller.bookmarked') ? 'bookmarked.clear_bookmarks' : 'bookmarked.title';
+ }.property('controller.bookmarked'),
+
rerenderTriggers: ['controller.bookmarked'],
helpKey: function() {
diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb
index b33655d349e..300027454cd 100644
--- a/app/controllers/posts_controller.rb
+++ b/app/controllers/posts_controller.rb
@@ -285,7 +285,9 @@ class PostsController < ApplicationController
PostAction.remove_act(current_user, post, PostActionType.types[:bookmark])
end
- render nothing: true
+ tu = TopicUser.get(post.topic, current_user)
+
+ render_json_dump(topic_bookmarked: tu.bookmarked)
end
def wiki
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
index ea002db4f86..499fba7bb06 100644
--- a/app/controllers/topics_controller.rb
+++ b/app/controllers/topics_controller.rb
@@ -217,15 +217,24 @@ class TopicsController < ApplicationController
render nothing: true
end
+ def remove_bookmarks
+ topic = Topic.find(params[:topic_id].to_i)
+
+ PostAction.joins(:post)
+ .where(user_id: current_user.id)
+ .where('topic_id = ?', topic.id).each do |pa|
+
+ PostAction.remove_act(current_user, pa.post, PostActionType.types[:bookmark])
+ end
+
+ render nothing: true
+ end
+
def bookmark
- topic = Topic.find_by(id: params[:topic_id])
+ topic = Topic.find(params[:topic_id].to_i)
first_post = topic.ordered_posts.first
- if params[:bookmarked] == "true"
- PostAction.act(current_user, first_post, PostActionType.types[:bookmark])
- else
- PostAction.remove_act(current_user, first_post, PostActionType.types[:bookmark])
- end
+ PostAction.act(current_user, first_post, PostActionType.types[:bookmark])
render nothing: true
end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index ba7629a5809..c93330443e9 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -167,9 +167,10 @@ en:
bookmarked:
title: "Bookmark"
+ clear_bookmarks: "Clear Bookmarks"
help:
- bookmark: "Click to bookmark this topic"
- unbookmark: "Click to remove bookmark to this topic"
+ bookmark: "Click to bookmark the first post on this topic"
+ unbookmark: "Click to remove all bookmarks in this topic"
bookmarks:
not_logged_in: "sorry, you must be logged in to bookmark posts"
@@ -2287,7 +2288,7 @@ en:
dismiss_topics: 'x, t Dismiss Topics'
actions:
title: 'Actions'
- bookmark_topic: 'f Bookmark topic'
+ bookmark_topic: 'f Toggle bookmark topic'
pin_unpin_topic: 'shift+p Pin/Unpin topic'
share_topic: 'shift+s Share topic'
share_post: 's Share post'
diff --git a/config/routes.rb b/config/routes.rb
index a6b2875f761..94d7d9ebd47 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -426,6 +426,7 @@ Discourse::Application.routes.draw do
post "t/:topic_id/change-owner" => "topics#change_post_owners", constraints: {topic_id: /\d+/}
delete "t/:topic_id/timings" => "topics#destroy_timings", constraints: {topic_id: /\d+/}
put "t/:topic_id/bookmark" => "topics#bookmark", constraints: {topic_id: /\d+/}
+ put "t/:topic_id/remove_bookmarks" => "topics#remove_bookmarks", constraints: {topic_id: /\d+/}
post "t/:topic_id/notifications" => "topics#set_notifications" , constraints: {topic_id: /\d+/}
diff --git a/spec/controllers/topics_controller_spec.rb b/spec/controllers/topics_controller_spec.rb
index 651e2fbc95b..4432b25b493 100644
--- a/spec/controllers/topics_controller_spec.rb
+++ b/spec/controllers/topics_controller_spec.rb
@@ -790,7 +790,7 @@ describe TopicsController do
it "works correctly" do
group = Fabricate(:group)
topic = Fabricate(:topic)
- admin = log_in(:admin)
+ _admin = log_in(:admin)
xhr :post, :invite, topic_id: topic.id, email: 'hiro@from.heros', group_ids: "#{group.id}"
@@ -857,7 +857,7 @@ describe TopicsController do
end
it 'needs you to be an admin or mod' do
- user = log_in
+ log_in
xhr :put, :autoclose, topic_id: 99, auto_close_time: '24', auto_close_based_on_last_post: false
expect(response).to be_forbidden
end
@@ -959,6 +959,25 @@ describe TopicsController do
end
end
+ describe 'remove_bookmarks' do
+ it "should remove bookmarks properly from non first post" do
+ bookmark = PostActionType.types[:bookmark]
+ user = log_in
+
+ post = create_post
+ post2 = create_post(topic_id: post.topic_id)
+
+ PostAction.act(user, post2, bookmark)
+
+ xhr :put, :bookmark, topic_id: post.topic_id
+ PostAction.where(user_id: user.id, post_action_type: bookmark).count.should == 2
+
+ xhr :put, :remove_bookmarks, topic_id: post.topic_id
+ PostAction.where(user_id: user.id, post_action_type: bookmark).count.should == 0
+
+ end
+ end
+
describe 'reset_new' do
it 'needs you to be logged in' do