FEATURE: Allow filtering users in group assigned tab (#95)

FEATURE: Allow filtering users in group assigned tab (#95)

diff --git a/app/controllers/discourse_assign/assign_controller.rb b/app/controllers/discourse_assign/assign_controller.rb
index c0d4a9f..faf9fa8 100644
--- a/app/controllers/discourse_assign/assign_controller.rb
+++ b/app/controllers/discourse_assign/assign_controller.rb
@@ -144,6 +144,10 @@ module DiscourseAssign
         .order('COUNT(users.id) DESC')
         .group('users.id')
         .select('users.*, COUNT(users.id) as "assignments_count"')
+
+        members = members.where("users.name ILIKE :pattern OR users.username_lower ILIKE :pattern", pattern: "%#{params[:filter]}%") if params[:filter]
+
+      members = members
         .limit(limit)
         .offset(offset)
 
diff --git a/assets/javascripts/discourse-assign/controllers/group-assigned.js.es6 b/assets/javascripts/discourse-assign/controllers/group-assigned.js.es6
index a8d8b16..693f016 100644
--- a/assets/javascripts/discourse-assign/controllers/group-assigned.js.es6
+++ b/assets/javascripts/discourse-assign/controllers/group-assigned.js.es6
@@ -1,13 +1,42 @@
 import { inject as service } from "@ember/service";
 import Controller, { inject as controller } from "@ember/controller";
 import { ajax } from "discourse/lib/ajax";
-import { observes } from "discourse-common/utils/decorators";
+import discourseComputed, { observes } from "discourse-common/utils/decorators";
+import discourseDebounce from "discourse/lib/debounce";
 
 export default Controller.extend({
   router: service(),
   application: controller(),
   loading: false,
   offset: 0,
+  filterName: "",
+  filter: "",
+
+  @discourseComputed("site.mobileView")
+  isDesktop(mobileView) {
+    return !mobileView;
+  },
+
+  @observes("filterName")
+  _setFilter: discourseDebounce(function() {
+    this.set("filter", this.filterName);
+  }, 500),
+
+  @observes("filter")
+  _filterModel() {
+    this.set("loading", true);
+    this.set("offset", 0);
+    ajax(`/assign/members/${this.group.name}`, {
+      type: "GET",
+      data: { filter: this.filter, offset: this.offset }
+    }).then(result => {
+      if (this.router.currentRoute.params.filter !== "everyone") {
+        this.transitionToRoute("group.assigned.show", "everyone");
+      }
+      this.set("members", result.members);
+      this.set("loading", false);
+    });
+  },
 
   @observes("model.assignment_count")
   assignmentCountChanged() {
@@ -27,12 +56,13 @@ export default Controller.extend({
     if (this.model.members.length >= this.offset + 50) {
       this.set("loading", true);
       this.set("offset", this.offset + 50);
-      ajax(`/assign/members/${this.group.name}?offset=${this.offset}`).then(
-        result => {
-          this.members.pushObjects(result.members);
-          this.set("loading", false);
-        }
-      );
+      ajax(`/assign/members/${this.group.name}`, {
+        type: "GET",
+        data: { filter: this.filter, offset: this.offset }
+      }).then(result => {
+        this.members.pushObjects(result.members);
+        this.set("loading", false);
+      });
     }
   },
 
diff --git a/assets/javascripts/discourse/templates/group/assigned.hbs b/assets/javascripts/discourse/templates/group/assigned.hbs
index 46f3a3e..db6b467 100644
--- a/assets/javascripts/discourse/templates/group/assigned.hbs
+++ b/assets/javascripts/discourse/templates/group/assigned.hbs
@@ -1,5 +1,10 @@
 <section class="user-secondary-navigation group-assignments">
   {{#mobile-nav class="activity-nav" desktopClass="action-list activity-list nav-stacked" currentPath=router._router.currentPath}}
+    {{#if isDesktop}}
+      <div class="search-div">
+        {{input type="text" placeholder=(i18n "discourse_assign.sidebar_name_filter_placeholder") value=filterName class="search"}}
+      </div>
+    {{/if}}
     {{#load-more selector=".activity-nav li" action=(action "loadMore")}}
       {{group-assigned-filter show-avatar=false filter="everyone" routeType=route_type assignment_count=group.assignment_count}}
       {{#each members as |member|}}
diff --git a/assets/stylesheets/assigns.scss b/assets/stylesheets/assigns.scss
index 9f49424..05d15ad 100644
--- a/assets/stylesheets/assigns.scss
+++ b/assets/stylesheets/assigns.scss
@@ -117,4 +117,11 @@
       grid-area: count;
     }
   }
+  .search {
+    height: 1em;
+    width: 100%;
+  }
+  .search-div {
+    padding: 13px;
+  }
 }
diff --git a/assets/stylesheets/mobile/assigns.scss b/assets/stylesheets/mobile/assigns.scss
index 58b153a..fb67ccc 100644
--- a/assets/stylesheets/mobile/assigns.scss
+++ b/assets/stylesheets/mobile/assigns.scss
@@ -39,7 +39,7 @@
     margin: 0;
     padding: 0;
   }
-  img {
+  a {
     width: 1em;
     height: 1em;
   }
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 753cd7b..261eec9 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -11,6 +11,7 @@ en:
       add_unassigned_filter: "Add 'unassigned' filter to category"
       cant_act: "You cannot act on flags that have been assigned to other users"
       cant_act_unclaimed: "You must claim this topic before acting on flags."
+      sidebar_name_filter_placeholder: "Name/Username"
       assigned: "Assigned"
       group_everyone: "Everyone"
       assigned_to: "Assigned to"
diff --git a/spec/requests/assign_controller_spec.rb b/spec/requests/assign_controller_spec.rb
index d8cca28..b040bc6 100644
--- a/spec/requests/assign_controller_spec.rb
+++ b/spec/requests/assign_controller_spec.rb
@@ -8,9 +8,9 @@ RSpec.describe DiscourseAssign::AssignController do
   before { SiteSetting.assign_enabled = true }
 
   let(:default_allowed_group) { Group.find_by(name: 'staff') }
-  let(:user) { Fabricate(:admin, groups: [default_allowed_group]) }
+  let(:user) { Fabricate(:admin, groups: [default_allowed_group], name: 'Robin Ward', username: 'eviltrout') }
   let(:post) { Fabricate(:post) }
-  let(:user2) { Fabricate(:active_user) }
+  let(:user2) { Fabricate(:active_user, name: 'David Tylor', username: 'david') }
   let(:nonadmin) { Fabricate(:user, groups: [default_allowed_group]) }
   let(:normal_user) { Fabricate(:user) }
   let(:normal_admin) { Fabricate(:admin) }
@@ -231,6 +231,22 @@ RSpec.describe DiscourseAssign::AssignController do
       expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user.id, user2.id])
     end
 
+    it "returns members as according to filter" do
+      sign_in(user)
+
+      get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: 'a' }
+      expect(response.status).to eq(200)
+      expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user.id, user2.id])
+
+      get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: 'david' }
+      expect(response.status).to eq(200)
+      expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user2.id])
+
+      get "/assign/members/#{get_assigned_allowed_group_name}.json", params: { filter: 'Tylor' }
+      expect(response.status).to eq(200)
+      expect(JSON.parse(response.body)['members'].map { |m| m['id'] }).to match_array([user2.id])
+    end
+
     it "404 error to non-group-members" do
       sign_in(normal_user)
 

GitHub sha: f250dca9

1 Like

This commit appears in #95 which was merged by davidtaylorhq.

this would be better in a finally because if ajax calls errors then you never stop the loading.