diff --git a/app/assets/javascripts/discourse/views/actions_history_view.js b/app/assets/javascripts/discourse/views/actions_history_view.js
index 24ef5e821d9..11931ac137d 100644
--- a/app/assets/javascripts/discourse/views/actions_history_view.js
+++ b/app/assets/javascripts/discourse/views/actions_history_view.js
@@ -27,10 +27,15 @@ Discourse.ActionsHistoryView = Discourse.View.extend({
var actionString, iconsHtml;
buffer.push("
");
+ // TODO multi line expansion for flags
+ var postUrl;
if (c.get('users')) {
iconsHtml = "";
c.get('users').forEach(function(u) {
iconsHtml += "
";
+ if (u.post_url) {
+ postUrl = postUrl || u.post_url;
+ }
iconsHtml += Discourse.Utilities.avatarImg({
size: 'small',
username: u.get('username'),
@@ -38,12 +43,17 @@ Discourse.ActionsHistoryView = Discourse.View.extend({
});
iconsHtml += "";
});
- buffer.push(" " + Em.String.i18n('post.actions.people.' + c.get('actionType.name_key'), { icons: iconsHtml }) + ".");
+
+ var key = 'post.actions.people.' + c.get('actionType.name_key');
+ if(postUrl) {
+ key = key + "_with_url";
+ }
+ buffer.push(" " + Em.String.i18n(key, { icons: iconsHtml, postUrl: postUrl}) + ".");
} else {
buffer.push("
" + (c.get('description')) + ".");
}
- if (c.get('can_act')) {
+ if (c.get('can_act') && !c.get('actionType.is_custom_flag')) {
actionString = Em.String.i18n("post.actions.it_too." + c.get('actionType.name_key'));
buffer.push("
" + actionString + ".");
}
diff --git a/app/controllers/post_actions_controller.rb b/app/controllers/post_actions_controller.rb
index 49d3b6dd65a..1312a22ae74 100644
--- a/app/controllers/post_actions_controller.rb
+++ b/app/controllers/post_actions_controller.rb
@@ -33,10 +33,17 @@ class PostActionsController < ApplicationController
guardian.ensure_can_see_post_actors!(@post.topic, post_action_type_id)
users = User.
+ select(['null as post_url','users.id', 'users.username', 'users.username_lower', 'users.email','post_actions.related_post_id']).
joins(:post_actions).
- where(["post_actions.post_id = ? and post_actions.post_action_type_id = ? and post_actions.deleted_at IS NULL", @post.id, post_action_type_id]).all
+ where(['post_actions.post_id = ? and post_actions.post_action_type_id = ? and post_actions.deleted_at IS NULL', @post.id, post_action_type_id]).all
- render_serialized(users, BasicUserSerializer)
+
+ urls = Post.urls(users.map{|u| u.related_post_id})
+ users.each do |u|
+ u.post_url = urls[u.related_post_id.to_i]
+ end
+
+ render_serialized(users, PostActionUserSerializer)
end
def destroy
diff --git a/app/models/post.rb b/app/models/post.rb
index ca247d53e85..464e5e6cbef 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -270,7 +270,26 @@ class Post < ActiveRecord::Base
end
def url
- "/t/#{Slug.for(topic.title)}/#{topic.id}/#{post_number}"
+ Post.url(topic.title, topic.id, post_number)
+ end
+
+ def self.url(title, topic_id, post_number)
+ "/t/#{Slug.for(title)}/#{topic_id}/#{post_number}"
+ end
+
+ def self.urls(post_ids)
+ ids = post_ids.map{|u| u}
+ if ids.length > 0
+ urls = {}
+ Topic.joins(:posts).where('posts.id' => ids).
+ select(['posts.id as post_id','post_number', 'topics.title', 'topics.id']).
+ each do |t|
+ urls[t.post_id.to_i] = url(t.title, t.id, t.post_number)
+ end
+ urls
+ else
+ {}
+ end
end
def author_readable
diff --git a/app/models/post_action.rb b/app/models/post_action.rb
index 9e0ff86d419..6793ff97c6d 100644
--- a/app/models/post_action.rb
+++ b/app/models/post_action.rb
@@ -6,7 +6,7 @@ class PostAction < ActiveRecord::Base
include RateLimiter::OnCreateRecord
- attr_accessible :post_action_type_id, :post_id, :user_id, :post, :user, :post_action_type, :message
+ attr_accessible :post_action_type_id, :post_id, :user_id, :post, :user, :post_action_type, :message, :related_post_id
belongs_to :post
belongs_to :user
@@ -89,16 +89,21 @@ class PostAction < ActiveRecord::Base
end
end
+ related_post_id = nil
if target_usernames.present?
- PostCreator.new(user,
+ related_post_id = PostCreator.new(user,
target_usernames: target_usernames,
archetype: Archetype.private_message,
subtype: subtype,
title: title,
raw: body
- ).create
+ ).create.id
end
- create(post_id: post.id, user_id: user.id, post_action_type_id: post_action_type_id, message: message)
+ create( post_id: post.id,
+ user_id: user.id,
+ post_action_type_id: post_action_type_id,
+ message: message,
+ related_post_id: related_post_id )
rescue ActiveRecord::RecordNotUnique
# can happen despite being .create
# since already bookmarked
diff --git a/app/serializers/post_action_user_serializer.rb b/app/serializers/post_action_user_serializer.rb
new file mode 100644
index 00000000000..19a4f6895c8
--- /dev/null
+++ b/app/serializers/post_action_user_serializer.rb
@@ -0,0 +1,8 @@
+class PostActionUserSerializer < BasicUserSerializer
+ attributes :post_url
+
+ # reserved
+ def post_url
+ object.post_url
+ end
+end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 0569f14ad74..7e94d76638c 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -622,8 +622,10 @@ en:
off_topic: "{{icons}} marked this as off-topic"
spam: "{{icons}} marked this as spam"
inappropriate: "{{icons}} marked this as inappropriate"
- notify_moderators: "{{icons}} flagged this"
+ notify_moderators: "{{icons}} notified moderators"
+ notify_moderators_with_url: "{{icons}}
notified moderators"
notify_user: "{{icons}} started a private conversation"
+ notify_user_with_url: "{{icons}} started a
private conversation"
bookmark: "{{icons}} bookmarked this"
like: "{{icons}} liked this"
vote: "{{icons}} voted for this"
diff --git a/db/migrate/20130422050626_add_related_post_id_to_post_actions.rb b/db/migrate/20130422050626_add_related_post_id_to_post_actions.rb
new file mode 100644
index 00000000000..7f3bbcf16c1
--- /dev/null
+++ b/db/migrate/20130422050626_add_related_post_id_to_post_actions.rb
@@ -0,0 +1,5 @@
+class AddRelatedPostIdToPostActions < ActiveRecord::Migration
+ def change
+ add_column :post_actions, :related_post_id, :integer
+ end
+end
diff --git a/spec/models/post_action_spec.rb b/spec/models/post_action_spec.rb
index f76de86309e..7a341ea9378 100644
--- a/spec/models/post_action_spec.rb
+++ b/spec/models/post_action_spec.rb
@@ -18,6 +18,23 @@ describe PostAction do
let(:bookmark) { PostAction.new(user_id: post.user_id, post_action_type_id: PostActionType.types[:bookmark] , post_id: post.id) }
describe "messaging" do
+
+ it "notify moderators integration test" do
+ mod = moderator
+ action = PostAction.act(codinghorror, post, PostActionType.types[:notify_moderators], "this is my special long message");
+
+ posts = Post.
+ joins(:topic).
+ select('posts.id, topics.subtype').
+ where('topics.archetype' => Archetype.private_message).
+ to_a
+
+ posts.count.should == 1
+ action.related_post_id.should == posts[0].id.to_i
+ posts[0].subtype.should == TopicSubtype.notify_moderators
+
+ end
+
describe 'notify_moderators' do
before do
PostAction.stubs(:create)
@@ -25,14 +42,8 @@ describe PostAction do
end
it "sends an email to all moderators if selected" do
- PostCreator.any_instance.expects(:create).returns(nil)
- PostAction.act(build(:user), build(:post), PostActionType.types[:notify_moderators], "this is my special message");
- end
-
- it "uses the correct topic subtype" do
- PostCreator.expects(:new).with do |user, opts|
- opts[:subtype] == TopicSubtype.notify_moderators
- end.returns(stub_everything)
+ post = build(:post, id: 1000)
+ PostCreator.any_instance.expects(:create).returns(post)
PostAction.act(build(:user), build(:post), PostActionType.types[:notify_moderators], "this is my special message");
end
end
@@ -45,14 +56,7 @@ describe PostAction do
end
it "sends an email to user if selected" do
- PostCreator.any_instance.expects(:create).returns(nil)
- PostAction.act(build(:user), post, PostActionType.types[:notify_user], "this is my special message");
- end
-
- it "uses the correct topic subtype" do
- PostCreator.expects(:new).with do |user, opts|
- opts[:subtype] == TopicSubtype.notify_user
- end.returns(stub_everything)
+ PostCreator.any_instance.expects(:create).returns(build(:post))
PostAction.act(build(:user), post, PostActionType.types[:notify_user], "this is my special message");
end
end
@@ -62,11 +66,10 @@ describe PostAction do
before do
PostAction.update_flagged_posts_count
end
- it "starts of with 0 flag counts" do
- PostAction.flagged_posts_count.should == 0
- end
it "increments the numbers correctly" do
+ PostAction.flagged_posts_count.should == 0
+
PostAction.act(codinghorror, post, PostActionType.types[:off_topic])
PostAction.flagged_posts_count.should == 1
@@ -108,7 +111,6 @@ describe PostAction do
end
-
describe 'when a user votes for something' do
it 'should increase the vote counts when a user likes' do
lambda {
diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb
index 9ac625b4253..6971bdf533a 100644
--- a/spec/models/post_spec.rb
+++ b/spec/models/post_spec.rb
@@ -333,18 +333,12 @@ describe Post do
it 'has one version in all_versions' do
post.all_versions.size.should == 1
+ first_version_at.should be_present
+ post.revise(post.user, post.raw).should be_false
end
- it "has an initial last_version" do
- first_version_at.should be_present
- end
describe 'with the same body' do
-
- it 'returns false' do
- post.revise(post.user, post.raw).should be_false
- end
-
it "doesn't change cached_version" do
lambda { post.revise(post.user, post.raw); post.reload }.should_not change(post, :cached_version)
end
@@ -383,13 +377,7 @@ describe Post do
it 'updates the cached_version' do
post.cached_version.should == 2
- end
-
- it 'creates a new version' do
post.all_versions.size.should == 2
- end
-
- it "updates the last_version_at" do
post.last_version_at.to_i.should == revised_at.to_i
end
@@ -445,31 +433,13 @@ describe Post do
let(:changed_by) { Fabricate(:coding_horror) }
let!(:result) { post.revise(changed_by, 'updated body') }
- it 'returns true' do
+ it 'acts correctly' do
result.should be_true
- end
-
- it 'updates the body' do
post.raw.should == 'updated body'
- end
-
- it 'sets the invalidate oneboxes attribute' do
post.invalidate_oneboxes.should == true
- end
-
- it 'increased the cached_version' do
post.cached_version.should == 2
- end
-
- it 'has the new version in all_versions' do
post.all_versions.size.should == 2
- end
-
- it 'has versions' do
post.versions.should be_present
- end
-
- it "saved the user who made the change in the version" do
post.versions.first.user.should be_present
end
@@ -482,9 +452,6 @@ describe Post do
it 'is a ninja edit, because the second poster posted again quickly' do
post.cached_version.should == 2
- end
-
- it 'is a ninja edit, because the second poster posted again quickly' do
post.all_versions.size.should == 2
end
@@ -544,39 +511,15 @@ describe Post do
let(:post) { Fabricate(:post, post_args) }
- it "defaults to not user_deleted" do
+ it "has correct info set" do
post.user_deleted?.should be_false
- end
-
- it 'has a post nubmer' do
post.post_number.should be_present
- end
-
- it 'has an excerpt' do
post.excerpt.should be_present
- end
-
- it 'is of the regular post type' do
post.post_type.should == Post.types[:regular]
- end
-
- it 'has no versions' do
post.versions.should be_blank
- end
-
- it 'has cooked content' do
post.cooked.should be_present
- end
-
- it 'has an external id' do
post.external_id.should be_present
- end
-
- it 'has no quotes' do
post.quote_count.should == 0
- end
-
- it 'has no replies' do
post.replies.should be_blank
end
@@ -584,19 +527,10 @@ describe Post do
let(:topic_user) { post.user.topic_users.where(topic_id: topic.id).first }
- it 'exists' do
+ it 'is set correctly' do
topic_user.should be_present
- end
-
- it 'has the posted flag set' do
topic_user.should be_posted
- end
-
- it 'recorded the latest post as read' do
topic_user.last_read_post_number.should == post.post_number
- end
-
- it 'recorded the latest post as the last seen' do
topic_user.seen_post_count.should == post.post_number
end
@@ -670,18 +604,11 @@ describe Post do
PostCreator.new(other_user, raw: raw, topic_id: topic.id, reply_to_post_number: post.post_number).create
end
- it 'has two quotes' do
+ it 'has the correct info set' do
multi_reply.quote_count.should == 2
- end
-
- it 'is a child of the parent post' do
post.replies.include?(multi_reply).should be_true
- end
-
- it 'is a child of the second post quoted' do
reply.replies.include?(multi_reply).should be_true
end
-
end
end
@@ -723,4 +650,17 @@ describe Post do
end
end
+ describe 'urls' do
+ it 'no-ops for empty list' do
+ Post.urls([]).should == {}
+ end
+
+ # integration test -> should move to centralized integration test
+ it 'finds urls for posts presented' do
+ p1 = Fabricate(:post)
+ p2 = Fabricate(:post)
+ Post.urls([p1.id, p2.id]).should == {p1.id => p1.url, p2.id => p2.url}
+ end
+ end
+
end
diff --git a/vendor/gems/discourse_poll/vendor/assets/javascripts/discourse_poll/templates/poll_controls.js.handlebars b/vendor/gems/discourse_poll/vendor/assets/javascripts/discourse_poll/templates/poll_controls.js.handlebars
index 5373c94f1c3..6c20d6fe0a6 100644
--- a/vendor/gems/discourse_poll/vendor/assets/javascripts/discourse_poll/templates/poll_controls.js.handlebars
+++ b/vendor/gems/discourse_poll/vendor/assets/javascripts/discourse_poll/templates/poll_controls.js.handlebars
@@ -14,4 +14,4 @@
{{#if view.post.voteAction.can_undo}}
undo
{{/if}}
-{{/if}}
\ No newline at end of file
+{{/if}}