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