FEATURE: better UI for group assignments (#197)

FEATURE: better UI for group assignments (#197)

On the group assignment page, we should be able to display

  • all topics assigned to that group + to user belonging to that group
  • all topics assigned directly to group
  • all topics assigned to individual user
diff --git a/app/controllers/discourse_assign/assign_controller.rb b/app/controllers/discourse_assign/assign_controller.rb
index 7df479a..22c54e9 100644
--- a/app/controllers/discourse_assign/assign_controller.rb
+++ b/app/controllers/discourse_assign/assign_controller.rb
@@ -126,17 +126,25 @@ module DiscourseAssign
         SQL
       end
 
-      assignment_count = Topic
-        .joins("JOIN assignments a ON a.topic_id = topics.id AND a.assigned_to_id IS NOT NULL ")
+      group_assignment_count = Topic
+        .joins("JOIN assignments a ON a.topic_id = topics.id")
         .where(<<~SQL, group_id: group.id)
-          (a.assigned_to_id IN (SELECT group_users.user_id FROM group_users WHERE group_id = :group_id) AND a.assigned_to_type = 'User')
-          OR
-          (a.assigned_to_id = :group_id AND a.assigned_to_type = 'Group')
+          a.assigned_to_id = :group_id AND a.assigned_to_type = 'Group'
         SQL
-        .where("topics.deleted_at IS NULL")
         .count
 
-      render json: { members: serialize_data(members, GroupUserAssignedSerializer), assignment_count: assignment_count }
+      assignment_count = Topic
+        .joins("JOIN assignments a ON a.topic_id = topics.id")
+        .joins("JOIN group_users ON group_users.user_id = a.assigned_to_id ")
+        .where("group_users.group_id = ?", group.id)
+        .where("a.assigned_to_type = 'User'")
+        .count
+
+      render json: {
+        members: serialize_data(members, GroupUserAssignedSerializer),
+        assignment_count: assignment_count + group_assignment_count,
+        group_assignment_count: group_assignment_count
+      }
     end
 
     private
diff --git a/assets/javascripts/discourse-assign/controllers/group-assigned-show.js.es6 b/assets/javascripts/discourse-assign/controllers/group-assigned-show.js.es6
index bdc5dfc..93d19b5 100644
--- a/assets/javascripts/discourse-assign/controllers/group-assigned-show.js.es6
+++ b/assets/javascripts/discourse-assign/controllers/group-assigned-show.js.es6
@@ -38,6 +38,7 @@ export default UserTopicsList.extend({
           order: this.order,
           ascending: this.ascending,
           search: this.search,
+          direct: this.model.params.direct,
         },
       })
       .then((result) => this.set("model", result))
diff --git a/assets/javascripts/discourse-assign/routes/group-assigned-show.js.es6 b/assets/javascripts/discourse-assign/routes/group-assigned-show.js.es6
index 7e6acde..c5f436c 100644
--- a/assets/javascripts/discourse-assign/routes/group-assigned-show.js.es6
+++ b/assets/javascripts/discourse-assign/routes/group-assigned-show.js.es6
@@ -13,12 +13,14 @@ export default DiscourseRoute.extend({
 
   model(params) {
     let filter = null;
-    if (params.filter !== "everyone") {
-      filter = `topics/messages-assigned/${params.filter}`;
-    } else {
+    if (
+      ["everyone", this.modelFor("group").get("name")].includes(params.filter)
+    ) {
       filter = `topics/group-topics-assigned/${this.modelFor("group").get(
         "name"
       )}`;
+    } else {
+      filter = `topics/messages-assigned/${params.filter}`;
     }
     const lastTopicList = findOrResetCachedTopicList(this.session, filter);
     return lastTopicList
@@ -29,6 +31,7 @@ export default DiscourseRoute.extend({
             order: params.order,
             ascending: params.ascending,
             search: params.search,
+            direct: params.filter !== "everyone",
           },
         });
   },
diff --git a/assets/javascripts/discourse-assign/routes/group-assigned.js.es6 b/assets/javascripts/discourse-assign/routes/group-assigned.js.es6
index 8d2e7b8..89f0ade 100644
--- a/assets/javascripts/discourse-assign/routes/group-assigned.js.es6
+++ b/assets/javascripts/discourse-assign/routes/group-assigned.js.es6
@@ -13,7 +13,10 @@ export default DiscourseRoute.extend({
       members: [],
       group: this.modelFor("group"),
     });
-    controller.group.set("assignment_count", model.assignment_count);
+    controller.group.setProperties({
+      assignment_count: model.assignment_count,
+      group_assignment_count: model.group_assignment_count,
+    });
 
     controller.findMembers(true);
   },
diff --git a/assets/javascripts/discourse/templates/components/group-assigned-filter.hbs b/assets/javascripts/discourse/templates/components/group-assigned-filter.hbs
index ccaa9cf..ad2dd4a 100644
--- a/assets/javascripts/discourse/templates/components/group-assigned-filter.hbs
+++ b/assets/javascripts/discourse/templates/components/group-assigned-filter.hbs
@@ -1,4 +1,4 @@
-{{#if show-avatar}}
+{{#if showAvatar}}
   {{#link-to "group.assigned.show" filter.username_lower (query-params order=order ascending=ascending search=search)}}
     <div class="assign-image">
       <a href={{filter.userPath}} data-user-card={{filter.username}}>{{avatar filter imageSize="large"}}</a>
@@ -13,6 +13,19 @@
       {{filter.assignments_count}}
     </div>
   {{/link-to}}
+{{else if groupName}}
+  {{#link-to "group.assigned.show" filter (query-params order=order ascending=ascending search=search)}}
+    <div class="assign-image">
+      {{d-icon "group-plus"}}
+    </div>
+    <div class="assign-names">
+      <div class="assign-username">{{groupName}}</div>
+    </div>
+
+    <div class="assign-count">
+      {{assignmentCount}}
+    </div>
+  {{/link-to}}
 {{else}}
   {{#link-to "group.assigned.show" filter (query-params order=order ascending=ascending search=search)}}
     <div class="assign-everyone">
diff --git a/assets/javascripts/discourse/templates/group/assigned.hbs b/assets/javascripts/discourse/templates/group/assigned.hbs
index 1ab424b..926d3ac 100644
--- a/assets/javascripts/discourse/templates/group/assigned.hbs
+++ b/assets/javascripts/discourse/templates/group/assigned.hbs
@@ -13,7 +13,7 @@
     {{/if}}
     {{#load-more selector=".activity-nav li" action=(action "loadMore")}}
       {{group-assigned-filter
-        show-avatar=false
+        showAvatar=false
         filter="everyone"
         routeType=route_type
         assignmentCount=group.assignment_count
@@ -21,9 +21,19 @@
         ascending=ascending
         order=order
       }}
+      {{group-assigned-filter
+        showAvatar=false
+        groupName=group.name
+        filter=group.name
+        routeType=route_type
+        assignmentCount=group.group_assignment_count
+        search=search
+        ascending=ascending
+        order=order
+      }}
       {{#each members as |member|}}
         {{group-assigned-filter
-          show-avatar=true
+          showAvatar=true
           filter=member
           routeType=route_type
           search=search
diff --git a/assets/stylesheets/assigns.scss b/assets/stylesheets/assigns.scss
index 93e9bbd..6285792 100644
--- a/assets/stylesheets/assigns.scss
+++ b/assets/stylesheets/assigns.scss
@@ -112,6 +112,16 @@
     align-items: center;
     padding: 0.5em 13px;
 
+    .assign-image {
+      width: 45px;
+      margin-right: 0.5em;
+      text-align: center;
+      svg {
+        width: 40px;
+        height: 40px;
+      }
+    }
+
     .assign-names {
       font-size: $font-down-1;
       grid-area: names;
diff --git a/db/migrate/20210908060141_add_index_to_assigned_to_id_and_type.rb b/db/migrate/20210908060141_add_index_to_assigned_to_id_and_type.rb
new file mode 100644
index 0000000..d11dfc8
--- /dev/null
+++ b/db/migrate/20210908060141_add_index_to_assigned_to_id_and_type.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddIndexToAssignedToIdAndType < ActiveRecord::Migration[6.1]
+  def change
+    add_index :assignments, [:assigned_to_id, :assigned_to_type]
+  end
+end
diff --git a/plugin.rb b/plugin.rb
index ebc3a51..c2c4dd9 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -275,34 +275,48 @@ after_initialize do
   add_to_class(:topic_query, :list_messages_assigned) do |user|
     list = default_results(include_pms: true)
 
-    list = list.where(<<~SQL, user_id: user.id)
-      topics.id IN (

[... diff too long, it was truncated ...]

GitHub sha: 62d87f0084001febe3612dcfba57f797fa07107f

This commit appears in #197 which was approved by tgxworld. It was merged by lis2.