Merge pull request #4137 from cpradio/add-warning-to-flag

FEATURE: Add warning input to flag dialog when notifying a user
This commit is contained in:
Sam 2016-04-15 16:23:22 +10:00
commit 9e50f36c50
10 changed files with 72 additions and 2 deletions

View File

@ -5,6 +5,7 @@ export default Ember.Controller.extend({
needs: ['flag'],
message: Em.computed.alias('controllers.flag.message'),
isWarning: Em.computed.alias('controllers.flag.isWarning'),
customPlaceholder: function(){
return I18n.t("flagging.custom_placeholder_" + this.get('model.name_key'));

View File

@ -7,6 +7,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
selected: null,
flagTopic: null,
message: null,
isWarning: false,
topicActionByName: null,
onShow() {
@ -118,6 +119,11 @@ export default Ember.Controller.extend(ModalFunctionality, {
});
},
createFlagAsWarning() {
this.send('createFlag', {isWarning: true});
this.set('model.hidden', true);
},
changePostActionType(action) {
this.set('selected', action);
},
@ -133,6 +139,12 @@ export default Ember.Controller.extend(ModalFunctionality, {
}
}.property('selected.name_key', 'userDetails.can_be_deleted', 'userDetails.can_delete_all_posts'),
canSendWarning: function() {
if (this.get("flagTopic")) return false;
return (Discourse.User.currentProp('staff') && this.get('selected.name_key') === 'notify_user');
}.property('selected.name_key'),
usernameChanged: function() {
this.set('userDetails', null);
this.fetchUserDetails();

View File

@ -59,6 +59,7 @@ export default RestModel.extend({
id: this.get('flagTopic') ? this.get('flagTopic.id') : post.get('id'),
post_action_type_id: this.get('id'),
message: opts.message,
is_warning: opts.isWarning,
take_action: opts.takeAction,
flag_topic: this.get('flagTopic') ? true : false
},

View File

@ -38,6 +38,10 @@
<div class="modal-footer">
<button class='btn btn-primary' {{action "createFlag"}} {{bind-attr disabled="submitDisabled"}} title="{{i18n 'flagging.submit_tooltip'}}">{{{submitText}}}</button>
{{#if canSendWarning}}
<button class="btn btn-danger" {{action "createFlagAsWarning" }} {{bind-attr disabled="submitDisabled"}} title="{{i18n 'flagging.official_warning'}}"><i class="fa fa-exclamation-triangle"></i> {{i18n 'flagging.official_warning'}}</button>
{{/if}}
{{#if canTakeAction}}
<button class='btn btn-danger' {{action "takeAction"}} {{bind-attr disabled="submitDisabled"}} title="{{i18n 'flagging.take_action_tooltip'}}"><i class="fa fa-gavel"></i>{{i18n 'flagging.take_action'}}</button>
{{/if}}

View File

@ -8,9 +8,11 @@ class PostActionsController < ApplicationController
def create
taken = PostAction.counts_for([@post], current_user)[@post.id]
guardian.ensure_post_can_act!(@post, PostActionType.types[@post_action_type_id], taken_actions: taken)
guardian.ensure_post_can_act!(@post, PostActionType.types[@post_action_type_id], is_warning: params[:is_warning])
args = {}
args[:message] = params[:message] if params[:message].present?
args[:is_warning] = params[:is_warning] if params[:is_warning].present? && guardian.is_staff?
args[:take_action] = true if guardian.is_staff? && params[:take_action] == 'true'
args[:flag_topic] = true if params[:flag_topic] == 'true'

View File

@ -215,11 +215,12 @@ SQL
title = I18n.t("post_action_types.#{post_action_type}.email_title", title: post.topic.title)
body = I18n.t("post_action_types.#{post_action_type}.email_body", message: opts[:message], link: "#{Discourse.base_url}#{post.url}")
warning = opts[:is_warning] if opts[:is_warning].present?
title = title.truncate(255, separator: /\s/)
opts = {
archetype: Archetype.private_message,
is_warning: warning,
title: title,
raw: body
}

View File

@ -1759,6 +1759,7 @@ en:
action: 'Flag Post'
take_action: "Take Action"
notify_action: 'Message'
official_warning: 'Official Warning'
delete_spammer: "Delete Spammer"
delete_confirm: "You are about to delete <b>%{posts}</b> posts and <b>%{topics}</b> topics from this user, remove their account, block signups from their IP address <b>%{ip_address}</b>, and add their email address <b>%{email}</b> to a permanent block list. Are you sure this user is really a spammer?"
yes_delete_spammer: "Yes, Delete Spammer"

View File

@ -32,6 +32,9 @@ module PostGuardian
# new users can't notify_user because they are not allowed to send private messages
not(action_key == :notify_user && !@user.has_trust_level?(SiteSetting.min_trust_to_send_messages)) &&
# non-staff can't send an official warning
not(action_key == :notify_user && !is_staff? && opts[:is_warning].present? && opts[:is_warning] == 'true') &&
# can't send private messages if they're disabled globally
not(action_key == :notify_user && !SiteSetting.enable_private_messages) &&

View File

@ -49,6 +49,17 @@ describe PostActionsController do
xhr :post, :create, id: @post.id, post_action_type_id: PostActionType.types[:like], message: 'action message goes here'
end
it 'passes the message through as warning' do
PostAction.expects(:act).once.with(@user, @post, PostActionType.types[:like], {message: 'action message goes here', is_warning: true})
xhr :post, :create, id: @post.id, post_action_type_id: PostActionType.types[:like], message: 'action message goes here', is_warning: true
end
it "doesn't create message as a warning if the user isn't staff" do
Guardian.any_instance.stubs(:is_staff?).returns(false)
PostAction.expects(:act).once.with(@user, @post, PostActionType.types[:like], {message: 'action message goes here'})
xhr :post, :create, id: @post.id, post_action_type_id: PostActionType.types[:like], message: 'action message goes here', is_warning: true
end
it 'passes take_action through' do
PostAction.expects(:act).once.with(@user, @post, PostActionType.types[:like], {take_action: true})
xhr :post, :create, id: @post.id, post_action_type_id: PostActionType.types[:like], take_action: 'true'

View File

@ -64,3 +64,37 @@ test("canDeleteSpammer spam selected", function(){
flagController.set('userDetails', buildAdminUser({can_delete_all_posts: false, can_be_deleted: false}));
canDeleteSpammer(flagController, 'spam', false, 'false if current user is staff, selected is spam, user cannot be deleted');
});
test("canSendWarning not staff", function(){
const store = createStore();
var flagController = this.subject({ model: buildPost() });
sandbox.stub(Discourse.User, 'currentProp').withArgs('staff').returns(false);
const notifyUserFlag = store.createRecord('post-action-type', {name_key: 'notify_user'});
flagController.set('selected', notifyUserFlag);
equal(flagController.get('canSendWarning'), false, 'false if current user is not staff');
});
var canSendWarning = function(flagController, postActionType, expected, testName) {
const store = createStore();
const flag = store.createRecord('post-action-type', {name_key: postActionType});
flagController.set('selected', flag);
equal(flagController.get('canSendWarning'), expected, testName);
};
test("canSendWarning notify_user not selected", function(){
sandbox.stub(Discourse.User, 'currentProp').withArgs('staff').returns(true);
var flagController = this.subject({ model: buildPost() });
canSendWarning(flagController, 'off_topic', false, 'false if current user is staff, but selected is off_topic');
canSendWarning(flagController, 'inappropriate', false, 'false if current user is staff, but selected is inappropriate');
canSendWarning(flagController, 'spam', false, 'false if current user is staff, but selected is spam');
canSendWarning(flagController, 'notify_moderators', false, 'false if current user is staff, but selected is notify_moderators');
});
test("canSendWarning notify_user selected", function(){
sandbox.stub(Discourse.User, 'currentProp').withArgs('staff').returns(true);
var flagController = this.subject({ model: buildPost() });
canSendWarning(flagController, 'notify_user', true, 'true if current user is staff, selected is notify_user');
});