From 5267e5bea6dc2056aa1b90baa6b1d52352a5d531 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 4 Feb 2014 12:56:28 +1100 Subject: [PATCH 01/18] BUGFIX: emails sent from "2 replies" as opposed to correct user --- app/jobs/regular/user_email.rb | 1 + app/mailers/user_notifications.rb | 2 +- app/models/post_alert_observer.rb | 3 +++ spec/jobs/user_email_spec.rb | 21 ++++++++++++++++++--- spec/mailers/user_notifications_spec.rb | 2 +- spec/models/notification_spec.rb | 8 ++++---- 6 files changed, 28 insertions(+), 9 deletions(-) diff --git a/app/jobs/regular/user_email.rb b/app/jobs/regular/user_email.rb index 69538e3a3e4..ab7bc548e19 100644 --- a/app/jobs/regular/user_email.rb +++ b/app/jobs/regular/user_email.rb @@ -41,6 +41,7 @@ module Jobs return if seen_recently && !user.suspended? # Load the post if present + email_args[:post] ||= Post.where(id: notification.data_hash[:original_post_id].to_i).first email_args[:post] ||= notification.post email_args[:notification] = notification diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb index 895c80318a3..f2d5cd661bc 100644 --- a/app/mailers/user_notifications.rb +++ b/app/mailers/user_notifications.rb @@ -127,7 +127,7 @@ class UserNotifications < ActionMailer::Base return unless @notification = opts[:notification] return unless @post = opts[:post] - username = @notification.data_hash[:display_username] + username = @notification.data_hash[:original_username] notification_type = opts[:notification_type] || Notification.types[@notification.notification_type].to_s context = "" diff --git a/app/models/post_alert_observer.rb b/app/models/post_alert_observer.rb index 290fcd8f3b1..0b6b4beff86 100644 --- a/app/models/post_alert_observer.rb +++ b/app/models/post_alert_observer.rb @@ -140,6 +140,7 @@ class PostAlertObserver < ActiveRecord::Observer end original_post = post + original_username = opts[:display_username] || post.username if collapsed post = first_unread_post(user,post.topic) || post @@ -155,6 +156,8 @@ class PostAlertObserver < ActiveRecord::Observer post_number: post.post_number, post_action_id: opts[:post_action_id], data: { topic_title: post.topic.title, + original_post_id: original_post.id, + original_username: original_username, display_username: opts[:display_username] || post.user.username }.to_json) end diff --git a/spec/jobs/user_email_spec.rb b/spec/jobs/user_email_spec.rb index 7dc726d136f..ce5d9ec7645 100644 --- a/spec/jobs/user_email_spec.rb +++ b/spec/jobs/user_email_spec.rb @@ -101,7 +101,16 @@ describe Jobs::UserEmail do context 'notification' do let(:post) { Fabricate(:post, user: user) } - let!(:notification) { Fabricate(:notification, user: user, topic: post.topic, post_number: post.post_number)} + let!(:notification) { + Fabricate(:notification, + user: user, + topic: post.topic, + post_number: post.post_number, + data: { + original_post_id: post.id + }.to_json + ) + } it 'passes a notification as an argument when a notification_id is present' do Email::Sender.any_instance.expects(:send) @@ -131,11 +140,17 @@ describe Jobs::UserEmail do before do @pm_from_staff = Fabricate(:post, user: Fabricate(:moderator)) @pm_from_staff.topic.topic_allowed_users.create!(user_id: suspended.id) - @pm_notification = Fabricate(:notification, user: suspended, topic: @pm_from_staff.topic, post_number: @pm_from_staff.post_number) + @pm_notification = Fabricate(:notification, + user: suspended, + topic: @pm_from_staff.topic, + post_number: @pm_from_staff.post_number, + data: { original_post_id: @pm_from_staff.id }.to_json + ) UserNotifications.expects(:user_private_message).with(suspended, notification: @pm_notification, post: @pm_from_staff).returns(mailer) end - subject(:execute_user_email_job) { Jobs::UserEmail.new.execute(type: :user_private_message, user_id: suspended.id, notification_id: @pm_notification.id) } + subject(:execute_user_email_job) { + Jobs::UserEmail.new.execute(type: :user_private_message, user_id: suspended.id, notification_id: @pm_notification.id) } it "sends an email" do execute_user_email_job diff --git a/spec/mailers/user_notifications_spec.rb b/spec/mailers/user_notifications_spec.rb index 836ffd675d4..57462825239 100644 --- a/spec/mailers/user_notifications_spec.rb +++ b/spec/mailers/user_notifications_spec.rb @@ -123,7 +123,7 @@ describe UserNotifications do topic: post.topic, notification_type: Notification.types[notification_type], post_number: post.post_number, - data: {display_username: username}.to_json ) + data: {original_username: username}.to_json ) end describe '.user_mentioned' do diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 0c5cf4d0d3a..652212a26b4 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -173,14 +173,14 @@ describe Notification do user_id: user.id, topic_id: 2, post_number: 1, - data: '[]', + data: {}.to_json, notification_type: Notification.types[:private_message]) other = Notification.create!(read: false, user_id: user.id, topic_id: 2, post_number: 1, - data: '[]', + data: {}.to_json, notification_type: Notification.types[:mentioned]) @@ -197,9 +197,9 @@ describe Notification do user = Fabricate(:user) (1..3).map do |i| - Notification.create!(read: false, user_id: user.id, topic_id: 2, post_number: i, data: '[]', notification_type: 1) + Notification.create!(read: false, user_id: user.id, topic_id: 2, post_number: i, data: '{}', notification_type: 1) end - Notification.create!(read: true, user_id: user.id, topic_id: 2, post_number: 4, data: '[]', notification_type: 1) + Notification.create!(read: true, user_id: user.id, topic_id: 2, post_number: 4, data: '{}', notification_type: 1) Notification.mark_posts_read(user,2,[1,2,3,4]).should == 3 end From d54f6faa35092d739afdc24bc23c94106588d3a5 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 4 Feb 2014 12:57:16 +1100 Subject: [PATCH 02/18] minor style fix --- lib/pretty_text.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index e430931f5a2..ff36fd5c167 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -236,12 +236,12 @@ module PrettyText def self.make_all_links_absolute(html) site_uri = nil doc = Nokogiri::HTML.fragment(html) - doc.css("a").each do |l| - href = l["href"].to_s + doc.css("a").each do |link| + href = link["href"].to_s begin uri = URI(href) site_uri ||= URI(Discourse.base_url) - l["href"] = "#{site_uri}#{l['href']}" unless uri.host.present? + link["href"] = "#{site_uri}#{link['href']}" unless uri.host.present? rescue URI::InvalidURIError # leave it end From 6c3c9345df7cdc6b8fff0160a0467341e41c2024 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 4 Feb 2014 12:57:52 +1100 Subject: [PATCH 03/18] use consistent style --- spec/models/notification_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 652212a26b4..c206206dfbd 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -173,14 +173,14 @@ describe Notification do user_id: user.id, topic_id: 2, post_number: 1, - data: {}.to_json, + data: '{}', notification_type: Notification.types[:private_message]) other = Notification.create!(read: false, user_id: user.id, topic_id: 2, post_number: 1, - data: {}.to_json, + data: '{}', notification_type: Notification.types[:mentioned]) From 04f1a5c3f8c374d25aa5905ab642958a5b2fe76e Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 4 Feb 2014 13:21:43 +1100 Subject: [PATCH 04/18] FEATURE: added welcome to discourse topic --- db/fixtures/999_topics.rb | 8 ++++++-- docs/WELCOME-TO-DISCOURSE.md | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 docs/WELCOME-TO-DISCOURSE.md diff --git a/db/fixtures/999_topics.rb b/db/fixtures/999_topics.rb index 472b596cef3..c244e8a888c 100644 --- a/db/fixtures/999_topics.rb +++ b/db/fixtures/999_topics.rb @@ -3,8 +3,12 @@ Topic.reset_column_information Post.reset_column_information if Topic.where('id NOT IN (SELECT topic_id from categories where topic_id is not null)').count == 0 && !Rails.env.test? - # seed welcome topic - puts "Seeding welcome topic" + puts "Seeding welcome topics" + welcome = File.read(Rails.root + 'docs/ADMIN-QUICK-START-GUIDE.md') PostCreator.create(Discourse.system_user, raw: welcome, title: "Discourse Admin Quick Start Guide" ,skip_validations: true) + + welcome = File.read(Rails.root + 'docs/WELCOME-TO-DISCOURSE.md') + post = PostCreator.create(Discourse.system_user, category: 'Meta', raw: welcome, title: "Welcome to Discourse", skip_validations: true) + post.topic.update_pinned(true) end diff --git a/docs/WELCOME-TO-DISCOURSE.md b/docs/WELCOME-TO-DISCOURSE.md new file mode 100644 index 00000000000..9b4edcb6b72 --- /dev/null +++ b/docs/WELCOME-TO-DISCOURSE.md @@ -0,0 +1 @@ +This is a placeholder for the welcome topic, to be filled by @codinghorror From 9bfe0e5a0ec81cd98272c5d13acef5cb2ce18c30 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 4 Feb 2014 13:29:16 +1100 Subject: [PATCH 05/18] BUGFIX: anon had skewed column titles --- .../discourse/templates/discovery/topics.js.handlebars | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars index 87b31ce47ad..9ab7faf4aa4 100644 --- a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars +++ b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars @@ -9,11 +9,13 @@ + {{#if currentUser}} + {{/if}} {{#sortable-heading sortBy="default" sortOrder=sortOrder}} {{i18n topic.title}} {{/sortable-heading}} From 612001aa74d71e0441918fe60209405a67b7cd4c Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 4 Feb 2014 15:14:10 +1100 Subject: [PATCH 06/18] BUGFIX: deleted categories would mess up watching/tracking prefs --- app/assets/javascripts/discourse/models/category.js | 9 +++++++-- test/javascripts/models/category_test.js | 9 +++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/discourse/models/category.js b/app/assets/javascripts/discourse/models/category.js index ca03fdc61b3..2df38bcdb5d 100644 --- a/app/assets/javascripts/discourse/models/category.js +++ b/app/assets/javascripts/discourse/models/category.js @@ -209,9 +209,14 @@ Discourse.Category.reopenClass({ }, findByIds: function(ids){ - return ids.map(function(id){ - return Discourse.Category.findById(id); + var categories = []; + _.each(ids, function(id){ + var found = Discourse.Category.findById(id); + if(found){ + categories.push(found); + } }); + return categories; }, findBySlug: function(slug, parentSlug) { diff --git a/test/javascripts/models/category_test.js b/test/javascripts/models/category_test.js index 04830483874..19a5dd313e7 100644 --- a/test/javascripts/models/category_test.js +++ b/test/javascripts/models/category_test.js @@ -39,6 +39,15 @@ test('findBySlug', function() { blank(Discourse.Category.findBySlug('luke', 'leia'), 'luke is blank with an incorrect parent'); }); +test('findByIds', function(){ + var categories = [ + Discourse.Category.create({id: 1}), + Discourse.Category.create({id: 2})]; + + this.stub(Discourse.Category, 'list').returns(categories); + deepEqual(Discourse.Category.findByIds([1,2,3]), categories); +}); + test('postCountStats', function() { var category1 = Discourse.Category.create({id: 1, slug: 'unloved', posts_year: 2, posts_month: 0, posts_week: 0, posts_day: 0}), category2 = Discourse.Category.create({id: 2, slug: 'hasbeen', posts_year: 50, posts_month: 4, posts_week: 0, posts_day: 0}), From dc77e7e27c6f2aaecdffe2ce1535e07ae0e4112e Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Tue, 4 Feb 2014 11:03:35 -0500 Subject: [PATCH 07/18] You must give a reason for suspending a user --- .../admin/controllers/admin_suspend_user_controller.js | 5 +++++ .../admin/templates/modal/admin_suspend_user.js.handlebars | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/admin/controllers/admin_suspend_user_controller.js b/app/assets/javascripts/admin/controllers/admin_suspend_user_controller.js index 0f4c1625ffd..14d9c862a98 100644 --- a/app/assets/javascripts/admin/controllers/admin_suspend_user_controller.js +++ b/app/assets/javascripts/admin/controllers/admin_suspend_user_controller.js @@ -9,8 +9,13 @@ **/ Discourse.AdminSuspendUserController = Discourse.ObjectController.extend(Discourse.ModalFunctionality, { + submitDisabled: function() { + return (!this.get('reason') || this.get('reason').length < 1); + }.property('reason'), + actions: { suspend: function() { + if (this.get('submitDisabled')) return; var duration = parseInt(this.get('duration'), 10); if (duration > 0) { var self = this; diff --git a/app/assets/javascripts/admin/templates/modal/admin_suspend_user.js.handlebars b/app/assets/javascripts/admin/templates/modal/admin_suspend_user.js.handlebars index 3bd276926ca..34a414cd072 100644 --- a/app/assets/javascripts/admin/templates/modal/admin_suspend_user.js.handlebars +++ b/app/assets/javascripts/admin/templates/modal/admin_suspend_user.js.handlebars @@ -10,6 +10,6 @@ From 359f03ca73f92bcc8bf25140ab96e2b9b8cc87f7 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 4 Feb 2014 12:10:52 -0500 Subject: [PATCH 08/18] FIX: Topic drafts weren't showing up properly. --- .../discourse/controllers/composer_controller.js | 6 +++--- .../javascripts/discourse/routes/discovery_route.js | 1 - .../discourse/routes/discovery_route_builders.js | 11 +++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/composer_controller.js b/app/assets/javascripts/discourse/controllers/composer_controller.js index 2ecbe46b255..1f32fb28a5b 100644 --- a/app/assets/javascripts/discourse/controllers/composer_controller.js +++ b/app/assets/javascripts/discourse/controllers/composer_controller.js @@ -333,14 +333,14 @@ Discourse.ComposerController = Discourse.Controller.extend({ cancelComposer: function() { var self = this; - return Ember.Deferred.promise(function (promise) { + return new Ember.RSVP.Promise(function (resolve) { if (self.get('model.hasMetaData') || self.get('model.replyDirty')) { bootbox.confirm(I18n.t("post.abandon"), I18n.t("no_value"), I18n.t("yes_value"), function(result) { if (result) { self.destroyDraft(); self.get('model').clearState(); self.close(); - promise.resolve(); + resolve(); } }); } else { @@ -348,7 +348,7 @@ Discourse.ComposerController = Discourse.Controller.extend({ self.destroyDraft(); self.get('model').clearState(); self.close(); - promise.resolve(); + resolve(); } }); }, diff --git a/app/assets/javascripts/discourse/routes/discovery_route.js b/app/assets/javascripts/discourse/routes/discovery_route.js index d83f0378e18..9ed230f969e 100644 --- a/app/assets/javascripts/discourse/routes/discovery_route.js +++ b/app/assets/javascripts/discourse/routes/discovery_route.js @@ -31,7 +31,6 @@ Discourse.DiscoveryRoute = Discourse.Route.extend({ this.controllerFor('composer').open({ categoryId: topicsController.get('category.id'), action: Discourse.Composer.CREATE_TOPIC, - draft: topicsController.get('draft'), draftKey: topicsController.get('draft_key'), draftSequence: topicsController.get('draft_sequence') }); diff --git a/app/assets/javascripts/discourse/routes/discovery_route_builders.js b/app/assets/javascripts/discourse/routes/discovery_route_builders.js index c9f75994d23..0ec08b890b4 100644 --- a/app/assets/javascripts/discourse/routes/discovery_route_builders.js +++ b/app/assets/javascripts/discourse/routes/discovery_route_builders.js @@ -28,6 +28,17 @@ function buildTopicRoute(filter) { Discourse.set('title', I18n.t('filters.with_topics', {filter: filterText})); this.controllerFor('discoveryTopics').setProperties({ model: model, category: null, period: period }); + + // If there's a draft, open the create topic composer + if (model.draft) { + this.controllerFor('composer').open({ + action: Discourse.Composer.CREATE_TOPIC, + draft: model.draft, + draftKey: model.draft_key, + draftSequence: model.draft_sequence + }); + } + this.controllerFor('navigationDefault').set('canCreateTopic', model.get('can_create_topic')); }, From 96016844058ce4d4e5ad5c2cf468cbca609ef70d Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Tue, 4 Feb 2014 12:26:38 -0500 Subject: [PATCH 09/18] Suggested topics includes closed and archived in new and unread, but not in random results --- lib/suggested_topics_builder.rb | 2 +- lib/topic_query.rb | 2 +- .../suggested_topics_builder_spec.rb | 6 ++-- spec/components/topic_query_spec.rb | 28 +++++++++++++++---- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lib/suggested_topics_builder.rb b/lib/suggested_topics_builder.rb index 9aec8a1daa6..bd4c3e54c6a 100644 --- a/lib/suggested_topics_builder.rb +++ b/lib/suggested_topics_builder.rb @@ -19,7 +19,7 @@ class SuggestedTopicsBuilder # Only add results if we don't have those topic ids already results = results.where('topics.id NOT IN (?)', @excluded_topic_ids) - .where(closed: false, archived: false, visible: true) + .where(visible: true) .to_a .reject { |topic| @category_topic_ids.include?(topic.id) } diff --git a/lib/topic_query.rb b/lib/topic_query.rb index a1faa1cb50f..c6f86c4f286 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -309,7 +309,7 @@ class TopicQuery end def random_suggested(topic, count, excluded_topic_ids=[]) - result = default_results(unordered: true, per_page: count) + result = default_results(unordered: true, per_page: count).where(closed: false, archived: false) excluded_topic_ids += Category.pluck(:topic_id).compact result = result.where("topics.id NOT IN (?)", excluded_topic_ids) unless excluded_topic_ids.empty? diff --git a/spec/components/suggested_topics_builder_spec.rb b/spec/components/suggested_topics_builder_spec.rb index dc2f17bfa9c..a10e3eddd76 100644 --- a/spec/components/suggested_topics_builder_spec.rb +++ b/spec/components/suggested_topics_builder_spec.rb @@ -83,14 +83,14 @@ describe SuggestedTopicsBuilder do end - context "adding invalid status topics" do + context "adding topics that are not open" do let!(:archived_topic) { Fabricate(:topic, archived: true)} let!(:closed_topic) { Fabricate(:topic, closed: true)} let!(:invisible_topic) { Fabricate(:topic, visible: false)} - it "doesn't add archived, closed or invisible topics" do + it "adds archived and closed, but not invisible topics" do builder.add_results(Topic) - builder.size.should == 0 + builder.size.should == 2 builder.should_not be_full end end diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index 76f5f82a11a..28e1410ed7d 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -366,7 +366,7 @@ describe TopicQuery do end end - context "anonymously browswing with invisible, closed and archived" do + context "anonymously browsing with invisible, closed and archived" do let!(:topic) { Fabricate(:topic) } let!(:regular_topic) { Fabricate(:post, user: creator).topic } let!(:closed_topic) { Fabricate(:topic, user: creator, closed: true) } @@ -394,12 +394,20 @@ describe TopicQuery do let!(:closed_topic) { Fabricate(:topic, user: creator, closed: true) } let!(:archived_topic) { Fabricate(:topic, user: creator, archived: true) } let!(:invisible_topic) { Fabricate(:topic, user: creator, visible: false) } + let!(:fully_read_closed) { Fabricate(:post, user: creator).topic } + let!(:fully_read_archived) { Fabricate(:post, user: creator).topic } before do user.auto_track_topics_after_msecs = 0 user.save TopicUser.update_last_read(user, partially_read.id, 0, 0) TopicUser.update_last_read(user, fully_read.id, 1, 0) + TopicUser.update_last_read(user, fully_read_closed.id, 1, 0) + TopicUser.update_last_read(user, fully_read_archived.id, 1, 0) + fully_read_closed.closed = true + fully_read_closed.save + fully_read_archived.archived = true + fully_read_archived.save end it "won't return new or fully read if there are enough partially read topics" do @@ -407,14 +415,22 @@ describe TopicQuery do suggested_topics.should == [partially_read.id] end - it "won't fully read if there are enough partially read topics and new topics" do - SiteSetting.stubs(:suggested_topics).returns(2) - suggested_topics.should == [partially_read.id, new_topic.id] + it "won't return fully read if there are enough partially read topics and new topics" do + SiteSetting.stubs(:suggested_topics).returns(4) + suggested_topics[0].should == partially_read.id + suggested_topics[1,3].should include(new_topic.id) + suggested_topics[1,3].should include(closed_topic.id) + suggested_topics[1,3].should include(archived_topic.id) end it "returns unread, then new, then random" do - SiteSetting.stubs(:suggested_topics).returns(3) - suggested_topics.should == [partially_read.id, new_topic.id, fully_read.id] + SiteSetting.stubs(:suggested_topics).returns(7) + suggested_topics[0].should == partially_read.id + suggested_topics[1,3].should include(new_topic.id) + suggested_topics[1,3].should include(closed_topic.id) + suggested_topics[1,3].should include(archived_topic.id) + suggested_topics[4].should == fully_read.id + # random doesn't include closed and archived end end From abffcd9f94a1763cd5bfa6201e8d04c4d7104e6b Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 4 Feb 2014 12:48:14 -0500 Subject: [PATCH 10/18] FIX: Blacklist `"), "hullo"); }); test("URLs in BBCode tags", function() { From 36683ff1e3838bb817e892c4045212cdc7c331a3 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 4 Feb 2014 13:19:36 -0500 Subject: [PATCH 11/18] FIX: Searching for spaces wouldn't stop spinning --- .../javascripts/discourse/controllers/search_controller.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/search_controller.js b/app/assets/javascripts/discourse/controllers/search_controller.js index c6db93b9ed1..ccb8c4c8e59 100644 --- a/app/assets/javascripts/discourse/controllers/search_controller.js +++ b/app/assets/javascripts/discourse/controllers/search_controller.js @@ -11,8 +11,8 @@ Discourse.SearchController = Em.ArrayController.extend(Discourse.Presence, { // If we need to perform another search newSearchNeeded: function() { this.set('noResults', false); - var term = this.get('term'); - if (term && term.length >= Discourse.SiteSettings.min_search_term_length) { + var term = (this.get('term') || '').trim(); + if (term.length >= Discourse.SiteSettings.min_search_term_length) { this.set('loading', true); this.searchTerm(term, this.get('typeFilter')); } else { @@ -57,6 +57,8 @@ Discourse.SearchController = Em.ArrayController.extend(Discourse.Presence, { self.set('urls', urls); } + self.set('loading', false); + }).catch(function() { self.set('loading', false); }); }, 300), From 4fb274fb9d8d8ecc4fc2db56a90d57263b3fef4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 4 Feb 2014 20:05:50 +0100 Subject: [PATCH 12/18] BUGFIX: history link doesn't work on deleted posts --- app/controllers/posts_controller.rb | 2 + lib/guardian.rb | 2 +- lib/guardian/post_guardian.rb | 4 +- spec/controllers/posts_controller_spec.rb | 61 +++++++++++++++++++- spec/fabricators/post_revision_fabricator.rb | 8 +++ spec/models/post_revision_spec.rb | 9 +++ spec/models/topic_revision_spec.rb | 9 +++ 7 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 spec/fabricators/post_revision_fabricator.rb create mode 100644 spec/models/post_revision_spec.rb create mode 100644 spec/models/topic_revision_spec.rb diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 58039f27aa9..69172b1c514 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -216,6 +216,8 @@ class PostsController < ApplicationController raise Discourse::InvalidParameters.new(:revision) if revision < 2 post_revision = PostRevision.where(post_id: post_id, number: revision).first + post_revision.post = find_post_from_params + guardian.ensure_can_see!(post_revision) post_revision end diff --git a/lib/guardian.rb b/lib/guardian.rb index a22340fc93c..d6709b40cf0 100644 --- a/lib/guardian.rb +++ b/lib/guardian.rb @@ -8,7 +8,7 @@ class Guardian include CategoryGuardian include PostGuardain include TopicGuardian - + class AnonymousUser def blank?; true; end def admin?; false; end diff --git a/lib/guardian/post_guardian.rb b/lib/guardian/post_guardian.rb index 9c9f660209b..7c1d041627d 100644 --- a/lib/guardian/post_guardian.rb +++ b/lib/guardian/post_guardian.rb @@ -104,7 +104,9 @@ module PostGuardain end def can_see_post_revision?(post_revision) - post_revision.present? && (is_staff? || can_see_post?(post_revision.post)) + return false if post_revision.nil? + return true if SiteSetting.edit_history_visible_to_public + authenticated? && (is_staff? || can_see_post?(post_revision.post)) end def can_vote?(post, opts={}) diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index 745f51b32ad..1780423346c 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe PostsController do - describe 'short_link' do it 'logs the incoming link once' do IncomingLink.expects(:add).once.returns(true) @@ -386,4 +385,64 @@ describe PostsController do end end + describe "revisions" do + + let(:post_revision) { Fabricate(:post_revision) } + + it "throws an exception when revision is < 2" do + expect { + xhr :get, :revisions, post_id: post_revision.post_id, revision: 1 + }.to raise_error(Discourse::InvalidParameters) + end + + context "when edit history is not visible to the public" do + + before { SiteSetting.stubs(:edit_history_visible_to_public).returns(false) } + + it "ensures anonymous can not see the revisions" do + xhr :get, :revisions, post_id: post_revision.post_id, revision: post_revision.number + response.should be_forbidden + end + + it "ensures staff can see the revisions" do + log_in(:admin) + xhr :get, :revisions, post_id: post_revision.post_id, revision: post_revision.number + response.should be_success + end + + it "ensures poster can see the revisions" do + user = log_in(:active_user) + pr = Fabricate(:post_revision, user: user) + xhr :get, :revisions, post_id: pr.post_id, revision: pr.number + response.should be_success + end + + end + + context "when edit history is visible to everyone" do + + before { SiteSetting.stubs(:edit_history_visible_to_public).returns(true) } + + it "ensures anyone can see the revisions" do + xhr :get, :revisions, post_id: post_revision.post_id, revision: post_revision.number + response.should be_success + end + + end + + context "deleted post" do + let(:admin) { log_in(:admin) } + let(:deleted_post) { Fabricate(:post, user: admin) } + let(:deleted_post_revision) { Fabricate(:post_revision, user: admin, post: deleted_post) } + + before { deleted_post.trash!(admin) } + + it "also work on deleted post" do + xhr :get, :revisions, post_id: deleted_post_revision.post_id, revision: deleted_post_revision.number + response.should be_success + end + end + + end + end diff --git a/spec/fabricators/post_revision_fabricator.rb b/spec/fabricators/post_revision_fabricator.rb new file mode 100644 index 00000000000..5a977b23829 --- /dev/null +++ b/spec/fabricators/post_revision_fabricator.rb @@ -0,0 +1,8 @@ +Fabricator(:post_revision) do + post + user + number 3 + modifications do + { "cooked" => ["

BEFORE

", "

AFTER

"], "raw" => ["BEFORE", "AFTER"] } + end +end diff --git a/spec/models/post_revision_spec.rb b/spec/models/post_revision_spec.rb new file mode 100644 index 00000000000..25c8e47bcee --- /dev/null +++ b/spec/models/post_revision_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' +require_dependency 'post_revision' + +describe PostRevision do + + it { should belong_to :user } + it { should belong_to :post } + +end diff --git a/spec/models/topic_revision_spec.rb b/spec/models/topic_revision_spec.rb new file mode 100644 index 00000000000..f1717ea9ee2 --- /dev/null +++ b/spec/models/topic_revision_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' +require_dependency 'topic_revision' + +describe TopicRevision do + + it { should belong_to :user } + it { should belong_to :topic } + +end From 13157b9b2edc11b5526c2e5488f9bd31849efa05 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 4 Feb 2014 14:37:49 -0500 Subject: [PATCH 13/18] Don't use crappy onebox failback to `title` --- Gemfile_rails4.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile_rails4.lock b/Gemfile_rails4.lock index 32c1f959485..1b382ef181b 100644 --- a/Gemfile_rails4.lock +++ b/Gemfile_rails4.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/dysania/onebox.git - revision: a02540f9b1460277e7132fbbd71a7d1dbeb486c2 + revision: 3753be3252dbb811f2ce94b56b55b5de54475a6c specs: onebox (1.1.0) hexpress (~> 1.2) From 659546c4e4fb338951c1761ebaa43f8bea91bbd3 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 4 Feb 2014 15:55:30 -0500 Subject: [PATCH 14/18] CHANGE: Hide category definition topics unless you are viewing that category. --- lib/topic_query.rb | 14 ++++++++------ spec/components/topic_query_spec.rb | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/topic_query.rb b/lib/topic_query.rb index c6f86c4f286..cee6faf2bdd 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -121,8 +121,7 @@ class TopicQuery end def list_category(category) - create_list(:category, unordered: true) do |list| - list = list.where(category_id: category.id) + create_list(:category, unordered: true, category: category.id) do |list| if @user list.order(TopicQuerySQL.order_with_pinned_sql) else @@ -132,10 +131,8 @@ class TopicQuery end def list_new_in_category(category) - create_list(:new_in_category, unordered: true) do |list| - list.where(category_id: category.id) - .by_newest - .first(25) + create_list(:new_in_category, unordered: true, category: category.id) do |list| + list.by_newest.first(25) end end @@ -242,6 +239,11 @@ class TopicQuery result = result.listable_topics.includes(category: :topic_only_relative_url) result = result.where('categories.name is null or categories.name <> ?', options[:exclude_category]).references(:categories) if options[:exclude_category] + # Don't include the category topic unless restricted to that category + if options[:category].blank? + result = result.where('COALESCE(categories.topic_id, 0) <> topics.id') + end + result = result.limit(options[:per_page]) unless options[:limit] == false result = result.visible if options[:visible] || @user.nil? || @user.regular? result = result.where.not(topics: {id: options[:except_topic_ids]}).references(:topics) if options[:except_topic_ids] diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index 28e1410ed7d..a530aa87baf 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -28,12 +28,12 @@ describe TopicQuery do Topic.recent(10).count.should == 0 # mods can see every group and hidden topics - TopicQuery.new(moderator).list_latest.topics.count.should == 3 + TopicQuery.new(moderator).list_latest.topics.count.should == 2 group.add(user) group.save - TopicQuery.new(user).list_latest.topics.count.should == 2 + TopicQuery.new(user).list_latest.topics.count.should == 1 end From f1b4c26e8e68d5eeb9171e12ed068d4a8cd0ab21 Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Tue, 4 Feb 2014 16:04:44 -0500 Subject: [PATCH 15/18] Add Mediapartners and AdsBot to list of user agents for Googlebot in browser-update.js.erb --- vendor/assets/javascripts/browser-update.js.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/assets/javascripts/browser-update.js.erb b/vendor/assets/javascripts/browser-update.js.erb index 76dd581cd76..6a27df4c949 100644 --- a/vendor/assets/javascripts/browser-update.js.erb +++ b/vendor/assets/javascripts/browser-update.js.erb @@ -19,12 +19,12 @@ var $buo = function() { // sam: my main concern here is mobile, but its an outlier, for now we support ie9, set conditionally and stuff with pushState if (window.ie === "new" || (window.history && window.history.pushState && !badAndroid)) { - return; + return; } // we don't ask Googlebot to update their browser - if (ua.indexOf('Googlebot') >= 0) { - return; + if (ua.indexOf('Googlebot') >= 0 || ua.indexOf('Mediapartners') >= 0 || ua.indexOf('AdsBot') >= 0) { + return; } // retrieve localized browser upgrade text From 8adb08a9ca2f69507b9deafaf67ad72659a010f9 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 4 Feb 2014 16:28:34 -0500 Subject: [PATCH 16/18] FIX: Don't allow `"), "press me!"); }); test("URLs in BBCode tags", function() { From 759c18d9f57b08ed225160f4db4e66336ae4dcb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 4 Feb 2014 23:25:27 +0100 Subject: [PATCH 17/18] FEATURE: HOME/END should always take you to the correct spot --- .../components/keyboard_shortcuts_component.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/discourse/components/keyboard_shortcuts_component.js b/app/assets/javascripts/discourse/components/keyboard_shortcuts_component.js index eea7f0ceac3..4be9ac9a9da 100644 --- a/app/assets/javascripts/discourse/components/keyboard_shortcuts_component.js +++ b/app/assets/javascripts/discourse/components/keyboard_shortcuts_component.js @@ -41,6 +41,8 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({ }, FUNCTION_BINDINGS: { + 'home': 'goToFirstPost', + 'end': 'goToLastPost', 'j': 'selectDown', 'k': 'selectUp', 'u': 'goBack', @@ -56,6 +58,14 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({ _.each(this.FUNCTION_BINDINGS, this._bindToFunction, this); }, + goToFirstPost: function() { + Discourse.__container__.lookup('controller:topic').send('jumpTop'); + }, + + goToLastPost: function() { + Discourse.__container__.lookup('controller:topic').send('jumpBottom'); + }, + selectDown: function() { this._moveSelection(1); }, @@ -77,7 +87,7 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({ }, showHelpModal: function() { - Discourse.__container__.lookup('controller:application').send("showKeyboardShortcutsHelp"); + Discourse.__container__.lookup('controller:application').send('showKeyboardShortcutsHelp'); }, _bindToPath: function(path, binding) { From df65371d720408dee2b11f7b9e96ffd354589a59 Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 5 Feb 2014 10:48:36 +1100 Subject: [PATCH 18/18] BUGFIX: microcontroller was consuming too much CPU sleep 0.1 and file test were expensive compared to a signal every second --- config/unicorn_launcher | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/unicorn_launcher b/config/unicorn_launcher index e0c277c9c77..60e20cf898b 100755 --- a/config/unicorn_launcher +++ b/config/unicorn_launcher @@ -33,7 +33,7 @@ UNICORN_PID=$! echo "supervisor pid: $UNICORN_SUPERVISOR_PID unicorn pid: $UNICORN_PID" -while [ -e /proc/$UNICORN_PID ] +while kill -0 $UNICORN_PID do - sleep 0.1 + sleep 1 done
{{#if canBulkSelect}} {{/if}}