diff --git a/app/assets/javascripts/discourse/controllers/topic_controller.js.coffee b/app/assets/javascripts/discourse/controllers/topic_controller.js.coffee
index 550f2cc0a..ebb0f33f4 100644
--- a/app/assets/javascripts/discourse/controllers/topic_controller.js.coffee
+++ b/app/assets/javascripts/discourse/controllers/topic_controller.js.coffee
@@ -259,6 +259,9 @@ Discourse.TopicController = Ember.ObjectController.extend Discourse.Presence,
post.toggleProperty('bookmarked')
false
+ clearFlags: (actionType) ->
+ actionType.clearFlags()
+
# Who acted on a particular post / action type
whoActed: (actionType) ->
actionType.loadUsers()
diff --git a/app/assets/javascripts/discourse/models/action_summary.js.coffee b/app/assets/javascripts/discourse/models/action_summary.js.coffee
index 554b29bdc..43023e50b 100644
--- a/app/assets/javascripts/discourse/models/action_summary.js.coffee
+++ b/app/assets/javascripts/discourse/models/action_summary.js.coffee
@@ -18,7 +18,7 @@ window.Discourse.ActionSummary = Em.Object.extend Discourse.Presence,
@set('acted', false)
@set('count', @get('count') - 1)
@set('can_act', true)
- @set('can_undo', false)
+ @set('can_undo', false)
# Perform this action
act: (opts) ->
@@ -52,16 +52,28 @@ window.Discourse.ActionSummary = Em.Object.extend Discourse.Presence,
@removeAction()
# Remove our post action
- jQuery.ajax
+ jQuery.ajax
url: "/post_actions/#{@get('post.id')}"
type: 'DELETE'
data:
- post_action_type_id: @get('id')
+ post_action_type_id: @get('id')
+
+ clearFlags: ->
+ $.ajax
+ url: "/post_actions/clear_flags"
+ type: "POST"
+ data:
+ post_action_type_id: @get('id')
+ id: @get('post.id')
+ success: (result) =>
+ @set('post.hidden', result.hidden)
+ @set('count', 0)
+
loadUsers: ->
$.getJSON "/post_actions/users",
id: @get('post.id'),
post_action_type_id: @get('id')
- (result) =>
+ (result) =>
@set('users', Em.A())
result.each (u) => @get('users').pushObject(Discourse.User.create(u))
diff --git a/app/assets/javascripts/discourse/views/actions_history_view.js.coffee b/app/assets/javascripts/discourse/views/actions_history_view.js.coffee
index 43de98102..50f6a30a6 100644
--- a/app/assets/javascripts/discourse/views/actions_history_view.js.coffee
+++ b/app/assets/javascripts/discourse/views/actions_history_view.js.coffee
@@ -35,12 +35,20 @@ window.Discourse.ActionsHistoryView = Em.View.extend Discourse.Presence,
if c.get('can_undo')
alsoName = Em.String.i18n("post.actions.undo", alsoName: c.get('actionType.alsoNameLower'))
- buffer.push(" #{alsoName}.")
+ buffer.push(" #{alsoName}.")
+
+ if c.get('can_clear_flags')
+ buffer.push(" #{Em.String.i18n("post.actions.clear_flags",count: c.count)}.")
+
buffer.push("")
click: (e) ->
$target = $(e.target)
+ if actionTypeId = $target.data('clear-flags')
+ @get('controller').clearFlags(@content.findProperty('id', actionTypeId))
+ return false
+
# User wants to know who actioned it
if actionTypeId = $target.data('who-acted')
@get('controller').whoActed(@content.findProperty('id', actionTypeId))
@@ -54,4 +62,4 @@ window.Discourse.ActionsHistoryView = Em.View.extend Discourse.Presence,
@get('controller').undoAction(@content.findProperty('id', actionTypeId))
return false
- false
\ No newline at end of file
+ false
diff --git a/app/controllers/post_actions_controller.rb b/app/controllers/post_actions_controller.rb
index 9031a4d03..f9d0e722e 100644
--- a/app/controllers/post_actions_controller.rb
+++ b/app/controllers/post_actions_controller.rb
@@ -45,6 +45,21 @@ class PostActionsController < ApplicationController
render nothing: true
end
+ def clear_flags
+ requires_parameter(:post_action_type_id)
+ raise Discourse::InvalidAccess unless guardian.is_admin?
+
+ PostAction.clear_flags!(@post, current_user.id, params[:post_action_type_id].to_i)
+ @post.reload
+
+ if @post.is_flagged?
+ render json: {success: true, hidden: true}
+ else
+ @post.unhide!
+ render json: {success: true, hidden: false}
+ end
+ end
+
private
def fetch_post_from_params
diff --git a/app/models/post.rb b/app/models/post.rb
index 1957cd532..6c0aff16f 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -250,6 +250,17 @@ class Post < ActiveRecord::Base
result
end
+ def is_flagged?
+ post_actions.where('post_action_type_id in (?) and deleted_at is null', PostActionType.FlagTypes).count != 0
+ end
+
+ def unhide!
+ self.hidden = false
+ self.hidden_reason_id = nil
+ self.topic.update_attributes(visible: true)
+ self.save
+ end
+
# Update the body of a post. Will create a new version when appropriate
def revise(updated_by, new_raw, opts={})
diff --git a/app/models/post_action.rb b/app/models/post_action.rb
index 089dc0d5f..91e5bc7c9 100644
--- a/app/models/post_action.rb
+++ b/app/models/post_action.rb
@@ -47,10 +47,14 @@ class PostAction < ActiveRecord::Base
user_actions
end
- def self.clear_flags!(post, moderator_id)
+ def self.clear_flags!(post, moderator_id, action_type_id = nil)
# -1 is the automatic system cleary
- actions = moderator_id == -1 ? PostActionType.AutoActionFlagTypes : PostActionType.FlagTypes
+ actions = if action_type_id
+ [action_type_id]
+ else
+ moderator_id == -1 ? PostActionType.AutoActionFlagTypes : PostActionType.FlagTypes
+ end
PostAction.exec_sql('update post_actions set deleted_at = ?, deleted_by = ?
where post_id = ? and deleted_at is null and post_action_type_id in (?)',
diff --git a/app/serializers/post_serializer.rb b/app/serializers/post_serializer.rb
index 45d01eedb..6a70dddc5 100644
--- a/app/serializers/post_serializer.rb
+++ b/app/serializers/post_serializer.rb
@@ -140,6 +140,8 @@ class PostSerializer < ApplicationSerializer
next if !action_summary[:can_act] && !scope.current_user
+ action_summary[:can_clear_flags] = scope.is_admin? && PostActionType.FlagTypes.include?(id)
+
if post_actions.present? and post_actions.has_key?(id)
action_summary[:acted] = true
action_summary[:can_undo] = scope.can_delete?(post_actions[id])
diff --git a/config/locales/en.yml b/config/locales/en.yml
index a86b81ffc..dd0527f53 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -853,6 +853,9 @@ en:
actions:
flag: 'Flag'
+ clear_flags:
+ one: "Clear flag"
+ other: "Clear flags"
it_too: "{{alsoName}} it too"
undo: "Undo {{alsoName}}"
by_you_and_others:
diff --git a/config/routes.rb b/config/routes.rb
index ce4e76db2..b0a8db092 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -133,6 +133,7 @@ Discourse::Application.routes.draw do
resources :post_actions do
collection do
get 'users' => 'post_actions#users'
+ post 'clear_flags' => 'post_actions#clear_flags'
end
end
resources :user_actions
diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb
index 682200f1a..00196c4bd 100644
--- a/spec/models/post_spec.rb
+++ b/spec/models/post_spec.rb
@@ -54,12 +54,29 @@ describe Post do
topic.user.trust_level = TrustLevel.Levels[:moderator]
Fabricate.build(:post, post_args).should be_valid
end
-
-
end
end
+ describe 'flagging helpers' do
+ it 'isFlagged is accurate' do
+ post = Fabricate(:post)
+ user = Fabricate(:coding_horror)
+ PostAction.act(user, post, PostActionType.Types[:off_topic])
+ PostAction.act(post.user, post, PostActionType.Types[:spam])
+
+ post.reload
+ post.is_flagged?.should == true
+
+ PostAction.remove_act(post.user, post, PostActionType.Types[:spam])
+ post.reload
+ post.is_flagged?.should == true
+
+ PostAction.remove_act(user, post, PostActionType.Types[:off_topic])
+ post.reload
+ post.is_flagged?.should == false
+ end
+ end
describe 'message bus' do
it 'enqueues the post on the message bus' do