diff --git a/app/assets/javascripts/discourse/components/radio_button.js b/app/assets/javascripts/discourse/components/radio_button.js new file mode 100644 index 000000000..1817064c9 --- /dev/null +++ b/app/assets/javascripts/discourse/components/radio_button.js @@ -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); diff --git a/app/assets/javascripts/discourse/controllers/bulk_notification_level_controller.js b/app/assets/javascripts/discourse/controllers/bulk_notification_level_controller.js new file mode 100644 index 000000000..60fb2a870 --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/bulk_notification_level_controller.js @@ -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'); + } + }); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/topic_bulk_actions_controller.js b/app/assets/javascripts/discourse/controllers/topic_bulk_actions_controller.js index 1b90f5831..8447491dd 100644 --- a/app/assets/javascripts/discourse/controllers/topic_bulk_actions_controller.js +++ b/app/assets/javascripts/discourse/controllers/topic_bulk_actions_controller.js @@ -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); diff --git a/app/assets/javascripts/discourse/models/topic.js b/app/assets/javascripts/discourse/models/topic.js index d46f1eb1d..dbbc5d16f 100644 --- a/app/assets/javascripts/discourse/models/topic.js +++ b/app/assets/javascripts/discourse/models/topic.js @@ -313,7 +313,7 @@ Discourse.Topic.reopenClass({ WATCHING: 3, TRACKING: 2, REGULAR: 1, - MUTE: 0 + MUTED: 0 }, createActionSummary: function(result) { diff --git a/app/assets/javascripts/discourse/routes/discovery_route.js b/app/assets/javascripts/discourse/routes/discovery_route.js index f9ef0695f..15a1df583 100644 --- a/app/assets/javascripts/discourse/routes/discovery_route.js +++ b/app/assets/javascripts/discourse/routes/discovery_route.js @@ -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() { diff --git a/app/assets/javascripts/discourse/templates/modal/bulk_actions_buttons.js.handlebars b/app/assets/javascripts/discourse/templates/modal/bulk_actions_buttons.js.handlebars index e17be58e3..0ae6fc38d 100644 --- a/app/assets/javascripts/discourse/templates/modal/bulk_actions_buttons.js.handlebars +++ b/app/assets/javascripts/discourse/templates/modal/bulk_actions_buttons.js.handlebars @@ -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> diff --git a/app/assets/javascripts/discourse/templates/modal/bulk_notification_level.js.handlebars b/app/assets/javascripts/discourse/templates/modal/bulk_notification_level.js.handlebars new file mode 100644 index 000000000..2dad1a349 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/modal/bulk_notification_level.js.handlebars @@ -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> diff --git a/app/assets/javascripts/discourse/views/buttons/notifications_button.js b/app/assets/javascripts/discourse/views/buttons/notifications_button.js index ef63571ba..a6978095e 100644 --- a/app/assets/javascripts/discourse/views/buttons/notifications_button.js +++ b/app/assets/javascripts/discourse/views/buttons/notifications_button.js @@ -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); diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index cb0ac26b9..db9f1095f 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -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." diff --git a/lib/topics_bulk_action.rb b/lib/topics_bulk_action.rb index 85d9a7396..5e31dc6ca 100644 --- a/lib/topics_bulk_action.rb +++ b/lib/topics_bulk_action.rb @@ -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) diff --git a/spec/components/topics_bulk_action_spec.rb b/spec/components/topics_bulk_action_spec.rb index 84233d57a..23637e40d 100644 --- a/spec/components/topics_bulk_action_spec.rb +++ b/spec/components/topics_bulk_action_spec.rb @@ -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) }