FEATURE: Can bulk update the notification level of topics

This commit is contained in:
Robin Ward 2014-02-14 17:38:55 -05:00
parent d0ecccb7e4
commit 3f3c07f136
11 changed files with 113 additions and 5 deletions

View file

@ -0,0 +1,13 @@
Discourse.RadioButton = Ember.Component.extend({
tagName : "input",
type : "radio",
attributeBindings : [ "name", "type", "value", "checked:checked" ],
click : function() {
this.set("selection", this.$().val());
},
checked : function() {
return this.get("value") === this.get("selection");
}.property('selection')
});
Em.Handlebars.helper('radio-button', Discourse.RadioButton);

View file

@ -0,0 +1,44 @@
/**
Support for changing the notification level of various topics
@class BulkNotificationLevelControler
@extends Ember.Controller
@namespace Discourse
@module Discourse
**/
Discourse.BulkNotificationLevelController = Em.Controller.extend({
needs: ['topicBulkActions', 'discoveryTopics'],
notificationLevelId: null,
notificationLevels: function() {
var result = [];
Object.keys(Discourse.Topic.NotificationLevel).forEach(function(k) {
result.push({
id: Discourse.Topic.NotificationLevel[k].toString(),
name: I18n.t('topic.notifications.' + k.toLowerCase() + ".title"),
description: I18n.t('topic.notifications.' + k.toLowerCase() + ".description")
});
});
return result;
}.property(),
disabled: Em.computed.empty("notificationLevelId"),
actions: {
changeNotificationLevel: function() {
var self = this;
this.get('controllers.topicBulkActions').perform({
type: 'change_notification_level',
notification_level_id: this.get('notificationLevelId')
}).then(function(topics) {
if (topics) {
// Tell current route to reload
self.get('controllers.discoveryTopics').send('refresh');
self.send('closeModal');
}
});
}
}
});

View file

@ -46,6 +46,10 @@ Discourse.TopicBulkActionsController = Ember.ArrayController.extend(Discourse.Mo
this.set('controllers.modal.modalClass', 'topic-bulk-actions-modal full');
},
showNotificationLevel: function() {
this.send('changeBulkTemplate', 'modal/bulk_notification_level');
},
closeTopics: function() {
this.forEachPerformed({type: 'close'}, function(t) {
t.set('closed', true);

View file

@ -313,7 +313,7 @@ Discourse.Topic.reopenClass({
WATCHING: 3,
TRACKING: 2,
REGULAR: 1,
MUTE: 0
MUTED: 0
},
createActionSummary: function(result) {

View file

@ -31,7 +31,10 @@ Discourse.DiscoveryRoute = Discourse.Route.extend(Discourse.OpenComposer, {
},
changeBulkTemplate: function(w) {
this.render(w, {into: 'topicBulkActions', outlet: 'bulkOutlet', controller: 'topicBulkActions'});
var controllerName = w.replace('modal/', ''),
factory = this.container.lookupFactory('controller:' + controllerName);
this.render(w, {into: 'topicBulkActions', outlet: 'bulkOutlet', controller: factory ? controllerName : 'topicBulkActions'});
},
showBulkActions: function() {

View file

@ -1,2 +1,3 @@
<button class='btn' {{action showChangeCategory}}>{{i18n topics.bulk.change_category}}</button>
<button class='btn' {{action closeTopics}}>{{i18n topics.bulk.close_topics}}</button>
<button class='btn' {{action showNotificationLevel}}>{{i18n topics.bulk.notification_level}}</button>

View file

@ -0,0 +1,10 @@
{{#each level in notificationLevels}}
<div class='controls'>
<label class='radio'>
{{radio-button value=level.id name="notification_level" selection=controller.notificationLevelId}} <strong>{{unbound level.name}}</strong>
<div class='description'>{{{unbound level.description}}}</div>
</label>
</div>
{{/each}}
<button class='btn' {{bind-attr disabled="disabled"}} {{action changeNotificationLevel}}>{{i18n topics.bulk.notification_level}}</button>

View file

@ -23,7 +23,7 @@ Discourse.NotificationsButton = Discourse.DropdownButtonView.extend({
['WATCHING', 'watching'],
['TRACKING', 'tracking'],
['REGULAR', 'regular'],
['MUTE', 'muted']
['MUTED', 'muted']
], function(pair) {
if (postfix === '_pm' && pair[1] === 'regular') { return; }
@ -42,7 +42,7 @@ Discourse.NotificationsButton = Discourse.DropdownButtonView.extend({
switch (this.get('topic.details.notification_level')) {
case Discourse.Topic.NotificationLevel.WATCHING: return 'watching';
case Discourse.Topic.NotificationLevel.TRACKING: return 'tracking';
case Discourse.Topic.NotificationLevel.MUTE: return 'muted';
case Discourse.Topic.NotificationLevel.MUTED: return 'muted';
default: return 'regular';
}
}).call(this);

View file

@ -627,6 +627,7 @@ en:
actions: "Bulk Actions"
change_category: "Change Category"
close_topics: "Close Topics"
notification_level: "Change Notification Level"
selected:
one: "You have selected <b>1</b> topic."
other: "You have selected <b>{{count}}</b> topics."

View file

@ -8,7 +8,7 @@ class TopicsBulkAction
end
def self.operations
%w(change_category close)
%w(change_category close change_notification_level)
end
def perform!
@ -27,6 +27,15 @@ class TopicsBulkAction
end
end
def change_notification_level
topics.each do |t|
if guardian.can_see?(t)
TopicUser.change(@user, t.id, notification_level: @operation[:notification_level_id].to_i)
@changed_ids << t.id
end
end
end
def close
topics.each do |t|
if guardian.can_moderate?(t)

View file

@ -38,6 +38,29 @@ describe TopicsBulkAction do
end
end
describe "change_notification_level" do
let(:topic) { Fabricate(:topic) }
context "when the user can edit the topic" do
it "updates the notification level" do
tba = TopicsBulkAction.new(topic.user, [topic.id], type: 'change_notification_level', notification_level_id: 2)
topic_ids = tba.perform!
topic_ids.should == [topic.id]
TopicUser.get(topic, topic.user).notification_level.should == 2
end
end
context "when the user can't edit the topic" do
it "doesn't change the level" do
Guardian.any_instance.expects(:can_see?).returns(false)
tba = TopicsBulkAction.new(topic.user, [topic.id], type: 'change_notification_level', notification_level_id: 2)
topic_ids = tba.perform!
topic_ids.should == []
TopicUser.get(topic, topic.user).should be_blank
end
end
end
describe "close" do
let(:topic) { Fabricate(:topic) }