From 1696cde2ff7b1e20b5668c5c3509172f071aa0e2 Mon Sep 17 00:00:00 2001
From: Robin Ward <robin.ward@gmail.com>
Date: Tue, 28 Jan 2014 17:13:13 -0500
Subject: [PATCH] Toggle button for bulk selection of topics

---
 .../controllers/discovery_topics_controller.js    | 10 +++++++++-
 .../controllers/topic_list_item_controller.js     | 15 +++++++++++++++
 .../templates/discovery/topics.js.handlebars      |  8 +++++---
 .../templates/list/topic_list_item.js.handlebars  | 10 ++++++++--
 .../discourse/views/list/topic_list_item_view.js  |  5 ++---
 app/assets/javascripts/discourse/views/view.js    |  2 --
 app/assets/stylesheets/desktop/topic-list.scss    | 11 +++++++++++
 config/locales/client.en.yml                      |  2 ++
 8 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/app/assets/javascripts/discourse/controllers/discovery_topics_controller.js b/app/assets/javascripts/discourse/controllers/discovery_topics_controller.js
index a9d4a0e1a..ace88ad3c 100644
--- a/app/assets/javascripts/discourse/controllers/discovery_topics_controller.js
+++ b/app/assets/javascripts/discourse/controllers/discovery_topics_controller.js
@@ -7,8 +7,10 @@
   @module Discourse
 **/
 Discourse.DiscoveryTopicsController = Discourse.DiscoveryController.extend({
-  actions: {
+  bulkSelectEnabled: false,
+  selected: [],
 
+  actions: {
     // Show newly inserted topics
     showInserted: function() {
       var tracker = Discourse.TopicTrackingState.current();
@@ -28,6 +30,11 @@ Discourse.DiscoveryTopicsController = Discourse.DiscoveryController.extend({
         self.set('model', list);
         self.send('loadingComplete');
       });
+    },
+
+    toggleBulkSelect: function() {
+      this.toggleProperty('bulkSelectEnabled');
+      this.get('selected').clear();
     }
   },
 
@@ -35,6 +42,7 @@ Discourse.DiscoveryTopicsController = Discourse.DiscoveryController.extend({
     return Discourse.TopicTrackingState.current();
   }.property(),
 
+  canBulkSelect: Em.computed.alias('currentUser.staff'),
   hasTopics: Em.computed.gt('topics.length', 0),
   showTable: Em.computed.or('hasTopics', 'topicTrackingState.hasIncoming'),
   allLoaded: Em.computed.empty('more_topics_url'),
diff --git a/app/assets/javascripts/discourse/controllers/topic_list_item_controller.js b/app/assets/javascripts/discourse/controllers/topic_list_item_controller.js
index 487a42507..80c6010f6 100644
--- a/app/assets/javascripts/discourse/controllers/topic_list_item_controller.js
+++ b/app/assets/javascripts/discourse/controllers/topic_list_item_controller.js
@@ -11,6 +11,21 @@ Discourse.TopicListItemController = Ember.ObjectController.extend({
 
   canStar: Em.computed.alias('controllers.discoveryTopics.currentUser.id'),
   hideCategory: Em.computed.alias('controllers.discoveryTopics.hideCategory'),
+  bulkSelectEnabled: Em.computed.alias('controllers.discoveryTopics.bulkSelectEnabled'),
+
+  checked: function(key, value) {
+    var selected = this.get('controllers.discoveryTopics.selected'),
+        topic = this.get('model');
+
+    if (arguments.length > 1) {
+      if (value) {
+        selected.addObject(topic);
+      } else {
+        selected.removeObject(topic);
+      }
+    }
+    return selected.contains(topic);
+  }.property('controllers.discoveryTopics.selected.length'),
 
   actions: {
     toggleStar: function() {
diff --git a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
index def3ba0d6..d6f217f72 100644
--- a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
@@ -3,9 +3,11 @@
     <table id='topic-list'>
       <thead>
       <tr>
-        {{#if currentUser}}
-          <th>&nbsp;</th>
-        {{/if}}
+        <th>
+          {{#if canBulkSelect}}
+          <button class='btn bulk-select' {{action toggleBulkSelect}} title="{{i18n topics.toggle_bulk_select}}"><i class='fa fa-list'></i></button>
+          {{/if}}
+        </th>
         {{#sortable-heading sortBy="default" sortOrder=sortOrder}}
           {{i18n topic.title}}
         {{/sortable-heading}}
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 8d4585db0..d02d7d23e 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
@@ -1,7 +1,13 @@
-{{#if canStar}}
+{{#if bulkSelectEnabled}}
   <td class='star'>
-    <a {{bind-attr class=":star :fa :fa-star starred:starred"}} {{action toggleStar}} href='#' {{bind-attr title="starTooltip"}}></a>
+    {{input type="checkbox" checked=checked}}
   </td>
+{{else}}
+  {{#if canStar}}
+    <td class='star'>
+      <a {{bind-attr class=":star :fa :fa-star starred:starred"}} {{action toggleStar}} href='#' {{bind-attr title="starTooltip"}}></a>
+    </td>
+  {{/if}}
 {{/if}}
 
 <td class='main-link clearfix'>
diff --git a/app/assets/javascripts/discourse/views/list/topic_list_item_view.js b/app/assets/javascripts/discourse/views/list/topic_list_item_view.js
index b59347dc9..d0c5bdf67 100644
--- a/app/assets/javascripts/discourse/views/list/topic_list_item_view.js
+++ b/app/assets/javascripts/discourse/views/list/topic_list_item_view.js
@@ -2,16 +2,15 @@
   This view handles the rendering of a topic in a list
 
   @class TopicListItemView
-  @extends Discourse.GroupedView
+  @extends Discourse.View
   @namespace Discourse
   @module Discourse
 **/
 Discourse.TopicListItemView = Discourse.GroupedView.extend({
   tagName: 'tr',
   templateName: 'list/topic_list_item',
-  classNameBindings: ['content.archived', ':topic-list-item', 'content.hasExcerpt:has-excerpt'],
+  classNameBindings: ['controller.checked', 'content.archived', ':topic-list-item', 'content.hasExcerpt:has-excerpt'],
   attributeBindings: ['data-topic-id'],
-
   'data-topic-id': Em.computed.alias('content.id'),
 
   highlight: function() {
diff --git a/app/assets/javascripts/discourse/views/view.js b/app/assets/javascripts/discourse/views/view.js
index 44f8ba5f1..b2b73cee4 100644
--- a/app/assets/javascripts/discourse/views/view.js
+++ b/app/assets/javascripts/discourse/views/view.js
@@ -21,8 +21,6 @@ Discourse.GroupedView = Ember.View.extend(Discourse.Presence, {
   }
 });
 
-
-
 Discourse.View.reopenClass({
 
   /**
diff --git a/app/assets/stylesheets/desktop/topic-list.scss b/app/assets/stylesheets/desktop/topic-list.scss
index 6d1f3aba7..150400ceb 100644
--- a/app/assets/stylesheets/desktop/topic-list.scss
+++ b/app/assets/stylesheets/desktop/topic-list.scss
@@ -69,6 +69,9 @@
     &:nth-child(even) {
       background-color: #f8f8f8;
     }
+    &.checked {
+      background-color: $highlight;
+    }
     &.archived a {
       opacity: 0.6;
     }
@@ -112,6 +115,14 @@
     font-size: 14px;
   }
 
+  button.bulk-select {
+    padding: 0;
+    background: transparent;
+    &:hover {
+      color: #999;
+    }
+  }
+
   .star {
     width: 20px;
     padding-right: 0;
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 92f882901..57d62d453 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -600,6 +600,8 @@ en:
         unstar: 'remove this topic from your starred list'
 
     topics:
+      toggle_bulk_select: "toggle bulk selection of topics"
+
       none:
         starred: "You haven't starred any topics yet. To star a topic, click or tap the star next to the title."
         unread: "You have no unread topics."