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 7d24571b0bb..37245d25a3e 100644
--- a/app/assets/javascripts/discourse/controllers/topic_bulk_actions_controller.js
+++ b/app/assets/javascripts/discourse/controllers/topic_bulk_actions_controller.js
@@ -10,5 +10,40 @@
Discourse.TopicBulkActionsController = Ember.ArrayController.extend(Discourse.ModalFunctionality, {
onShow: function() {
this.set('controllers.modal.modalClass', 'topic-bulk-actions-modal');
+ },
+
+ perform: function(operation) {
+ this.set('loading', true);
+
+ var self = this,
+ topics = this.get('model');
+ return Discourse.Topic.bulkOperation(this.get('model'), operation).then(function(result) {
+ self.set('loading', false);
+ if (result && result.topic_ids) {
+ return result.topic_ids.map(function (t) {
+ return topics.findBy('id', t);
+ });
+ }
+ return result;
+ }).catch(function() {
+ self.set('loading', false);
+ });
+ },
+
+ actions: {
+ showChangeCategory: function() {
+ this.send('changeBulkTemplate', 'modal/bulk_change_category');
+ },
+
+ changeCategory: function() {
+ var category = Discourse.Category.findById(parseInt(this.get('newCategoryId'), 10)),
+ self = this;
+ this.perform({type: 'change_category', category_id: this.get('newCategoryId')}).then(function(topics) {
+ topics.forEach(function(t) {
+ t.set('category', category);
+ });
+ self.send('closeModal');
+ });
+ }
}
});
diff --git a/app/assets/javascripts/discourse/models/topic.js b/app/assets/javascripts/discourse/models/topic.js
index 3a0cefa1b5a..5513e4c1a2e 100644
--- a/app/assets/javascripts/discourse/models/topic.js
+++ b/app/assets/javascripts/discourse/models/topic.js
@@ -382,6 +382,16 @@ Discourse.Topic.reopenClass({
promise.reject(new Error("error moving posts topic"));
});
return promise;
+ },
+
+ bulkOperation: function(topics, operation) {
+ return Discourse.ajax("/topics/bulk", {
+ type: 'PUT',
+ data: {
+ topic_ids: topics.map(function(t) { return t.get('id'); }),
+ operation: operation
+ }
+ });
}
});
diff --git a/app/assets/javascripts/discourse/routes/discovery_route.js b/app/assets/javascripts/discourse/routes/discovery_route.js
index 6fbf9e8d838..d83f0378e18 100644
--- a/app/assets/javascripts/discourse/routes/discovery_route.js
+++ b/app/assets/javascripts/discourse/routes/discovery_route.js
@@ -37,9 +37,14 @@ Discourse.DiscoveryRoute = Discourse.Route.extend({
});
},
+ changeBulkTemplate: function(w) {
+ this.render(w, {into: 'topicBulkActions', outlet: 'bulkOutlet', controller: 'topicBulkActions'});
+ },
+
showBulkActions: function() {
var selected = this.controllerFor('discoveryTopics').get('selected');
Discourse.Route.showModal(this, 'topicBulkActions', selected);
+ this.send('changeBulkTemplate', 'modal/bulk_actions_buttons');
}
}
});
diff --git a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
index c23fcd04941..87b31ce47ad 100644
--- a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
@@ -11,7 +11,7 @@
{{#if canBulkSelect}}
-
+
{{/if}}
|
{{#sortable-heading sortBy="default" sortOrder=sortOrder}}
diff --git a/app/assets/javascripts/discourse/templates/list/topic_list_item.js.handlebars b/app/assets/javascripts/discourse/templates/list/topic_list_item.js.handlebars
index d02d7d23e60..0f5281f80c1 100644
--- a/app/assets/javascripts/discourse/templates/list/topic_list_item.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/list/topic_list_item.js.handlebars
@@ -37,7 +37,7 @@
{{#unless hideCategory}}
-{{categoryLink category}} |
+{{boundCategoryLink category}} |
{{/unless}}
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
new file mode 100644
index 00000000000..88c8763eb0b
--- /dev/null
+++ b/app/assets/javascripts/discourse/templates/modal/bulk_actions_buttons.js.handlebars
@@ -0,0 +1 @@
+
diff --git a/app/assets/javascripts/discourse/templates/modal/bulk_change_category.js.handlebars b/app/assets/javascripts/discourse/templates/modal/bulk_change_category.js.handlebars
new file mode 100644
index 00000000000..6a5fe566a58
--- /dev/null
+++ b/app/assets/javascripts/discourse/templates/modal/bulk_change_category.js.handlebars
@@ -0,0 +1,10 @@
+ Choose the new category for the topics:
+
+{{categoryChooser value=newCategoryId}}
+
+{{#if loading}}
+ {{i18n loading}}
+{{else}}
+
+{{/if}}
+
diff --git a/app/assets/javascripts/discourse/templates/modal/topic_bulk_actions.js.handlebars b/app/assets/javascripts/discourse/templates/modal/topic_bulk_actions.js.handlebars
index e0368634dc3..92d3a03e6a3 100644
--- a/app/assets/javascripts/discourse/templates/modal/topic_bulk_actions.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/modal/topic_bulk_actions.js.handlebars
@@ -1,7 +1,7 @@
- {{{i18n topics.selected count=length}}}
+ {{{i18n topics.bulk.selected count=length}}}
-
+ {{outlet bulkOutlet}}
diff --git a/app/assets/javascripts/discourse/views/topic_bulk_actions_view.js b/app/assets/javascripts/discourse/views/topic_bulk_actions_view.js
index 53eee4ba5bc..a72348415e3 100644
--- a/app/assets/javascripts/discourse/views/topic_bulk_actions_view.js
+++ b/app/assets/javascripts/discourse/views/topic_bulk_actions_view.js
@@ -8,5 +8,5 @@
**/
Discourse.TopicBulkActionsView = Discourse.ModalBodyView.extend({
templateName: 'modal/topic_bulk_actions',
- title: I18n.t('topics.bulk_actions')
+ title: I18n.t('topics.bulk.actions')
});
diff --git a/app/assets/stylesheets/desktop/modal.scss b/app/assets/stylesheets/desktop/modal.scss
index 4c7ec965ca3..8445d42a43a 100644
--- a/app/assets/stylesheets/desktop/modal.scss
+++ b/app/assets/stylesheets/desktop/modal.scss
@@ -251,6 +251,10 @@
p {
margin-top: 0;
}
+ .modal-body {
+ height: 420px;
+ max-height: 420px;
+ }
}
.tabbed-modal {
.modal-body {
diff --git a/app/assets/stylesheets/desktop/topic-list.scss b/app/assets/stylesheets/desktop/topic-list.scss
index d8098c18c32..2881416d344 100644
--- a/app/assets/stylesheets/desktop/topic-list.scss
+++ b/app/assets/stylesheets/desktop/topic-list.scss
@@ -69,9 +69,6 @@
&:nth-child(even) {
background-color: #f8f8f8;
}
- &.checked {
- background-color: $highlight;
- }
&.archived a {
opacity: 0.6;
}
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
index fc8dd43e99e..f2dec37ced3 100644
--- a/app/controllers/topics_controller.rb
+++ b/app/controllers/topics_controller.rb
@@ -19,7 +19,8 @@ class TopicsController < ApplicationController
:move_posts,
:merge_topic,
:clear_pin,
- :autoclose]
+ :autoclose,
+ :bulk]
before_filter :consider_user_for_promotion, only: :show
@@ -266,6 +267,11 @@ class TopicsController < ApplicationController
render 'topics/show', formats: [:rss]
end
+ def bulk
+ topic_ids = params.require(:topic_ids).map {|t| t.to_i}
+ render_json_dump topic_ids: topic_ids
+ end
+
private
def toggle_mute
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 2c99efe14fb..0d16de9cde4 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -600,11 +600,13 @@ en:
unstar: 'remove this topic from your starred list'
topics:
- toggle_bulk_select: "toggle bulk selection of topics"
- bulk_actions: "Bulk Actions"
- selected:
- one: "You have selected 1 topic."
- other: "You have selected {{count}} topics."
+ bulk:
+ toggle: "toggle bulk selection of topics"
+ actions: "Bulk Actions"
+ change_category: "Change Category"
+ selected:
+ one: "You have selected 1 topic."
+ other: "You have selected {{count}} topics."
none:
starred: "You haven't starred any topics yet. To star a topic, click or tap the star next to the title."
diff --git a/config/routes.rb b/config/routes.rb
index 4b232420f28..f782d0b74e6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -242,6 +242,7 @@ Discourse::Application.routes.draw do
post "t" => "topics#create"
put "t/:id" => "topics#update"
delete "t/:id" => "topics#destroy"
+ put "topics/bulk"
post "topics/timings"
get "topics/similar_to"
get "topics/created-by/:username" => "list#topics_by", as: "topics_by", constraints: {username: USERNAME_ROUTE_FORMAT}
|