0

I am updating the rocket chat app to have a departments filter on the department list page. I am running into an issue where my filter seems to be tied to the same collection as the result set. So when I update the filter all the other filter options are removed. I'm not sure the best way to make it so the filter only impacts the result list and not both.

Before: enter image description here

After: enter image description here HTML

<template name="livechatDepartments">
{{#requiresPermission 'view-livechat-manager'}}
<fieldset>
<form class="form-inline" method="post">
    <div class="form-group">
        <label for="department">{{_ "Department"}}</label>
        <select name="department">
            <option value=""></option>
            {{#each departmentsDDL}}
                <option value="{{_id}}">{{name}}</option>
            {{/each}}
        </select>
    </div>

    <div class="form-group">
        <label for="agent">{{_ "Served_By"}}</label>
        <select name="agent">
            <option value=""></option>
            {{#each agents}}
                <option value="{{_id}}">{{username}}</option>
            {{/each}}
        </select>
    </div>
    <button class="button">{{_ "Filter"}}</button>
</form>
</fieldset>
    <div class="list">
        <table>
            <thead>
                <tr>
                    <th width="20%">{{_ "Name"}}</th>
                    <th width="30%">{{_ "Description"}}</th>
                    <th width="10%">{{_ "Num_Agents"}}</th>
                    <th width="10%">{{_ "Num_Available_Agents"}}</th>
                    <th width="20%">{{_ "Enabled"}}</th>
                    <th width="20%">{{_ "Show_on_registration_page"}}</th>
                    <th>{{_ "Delete"}}</th>
                </tr>
            </thead>
            <tbody>
                {{#each departments}}
                    <tr class="department-info row-link" data-id="{{_id}}">
                        <td>{{name}}</td>
                        <td>{{description}}</td>
                        <td>{{numAgents}}</td>
                        <!--<td>{{}}</td>-->
                        <td>{{#if enabled}}{{_ "Yes"}}{{else}}{{_ "No"}}{{/if}}</td>
                        <td>{{#if showOnRegistration}}{{_ "Yes"}}{{else}}{{_ "No"}}{{/if}}</td>
                        <td><a href="#remove" class="remove-department"><i class="icon-trash"></i></a></td>
                    </tr>
                {{/each}}
            </tbody>
        </table>
    </div>
    <div class="text-center">
        <button class="button load-more">{{_ "Load_more"}}</button>
    </div>
    <a href="{{pathFor 'livechat-department-new'}}" class="button primary">{{_ "New_Department"}}</a>
{{/requiresPermission}}

JS:

Template.livechatDepartments.helpers({
  departmentsDDL() {
    return LivechatDepartment.find({}, { sort: { name: -1 } });
  },

  departments() {
    return LivechatDepartment.find({}, { sort: { name: -1 } });
  },

  agents() {
    return AgentUsers.find({}, { sort: { name: 1 } });
  }
});

Template.livechatDepartments.events({
  'click .remove-department' (e /*, instance*/ ) {
    e.preventDefault();
    e.stopPropagation();
    swal({
      title: t('Are_you_sure'),
      type: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#DD6B55',
      confirmButtonText: t('Yes'),
      cancelButtonText: t('Cancel'),
      closeOnConfirm: false,
      html: false
    }, () => {
      Meteor.call('livechat:removeDepartment', this._id, function(error /*, result*/ ) {
        if (error) { return handleError(error); }
        swal({
          title: t('Removed'),
          text: t('Department_removed'),
          type: 'success',
          timer: 1000,
          showConfirmButton: false
        });
      });
    });
  },

  'click .department-info' (e /*, instance*/ ) {
    e.preventDefault();
    FlowRouter.go('livechat-department-edit', { _id: this._id });
  },

  'submit form' (e, instance) {
    e.preventDefault();
    const filter = {};
    $(':input', event.currentTarget)
      .each(function() {
        if (this.name) {
          filter[this.name] = $(this)
            .val();
        }
      });
    instance.filter.set(filter);
    instance.limit.set(20);
  }
});

Template.livechatDepartments.onCreated(function() {
  this.limit = new ReactiveVar(20);
  this.filter = new ReactiveVar({});

  this.subscribe('livechat:agents');

  this.autorun(() => {
    this.subscribe('livechat:departments', this.filter.get(), 0, this.limit.get());
  });
});

Meteor Method:

Meteor.publish("livechat:departments", function(filter = {}, offset = 0, limit = 20) {
      if (!this.userId) {
        return this.error(
          new Meteor.Error("error-not-authorized", "Not authorized", {
            publish: "livechat:agents"
          })
        );
      }

      if (!RocketChat.authz.hasPermission(this.userId, "view-l-room")) {
        return this.error(
          new Meteor.Error("error-not-authorized", "Not authorized", {
            publish: "livechat:agents"
          })
        );
      }

      check(filter, {
        agent: Match.Maybe(String), // agent _id who is serving
        department: Match.Maybe(String)
      });

      const query = {};
      if (filter.agent) {

        const DepartmentFilter = [];
        RocketChat.models.LivechatDepartmentAgents
          .find({
            agentId: filter.agent
          })
          .forEach(department => {
            DepartmentFilter.push(department);
          });

        var depts = DepartmentFilter.map(function(dep) {
          return dep.departmentId;
        });
JeremyK
  • 3,240
  • 1
  • 11
  • 24
John Graham
  • 573
  • 4
  • 20

1 Answers1

1

As you stated in the question, your filter is tied to the same collection as your results set. So, how can you fix this?

Solution 1 - Easy, and if data in livechat:departments collection is not too large, probably the best:

  • Revert back your subscription code to fetch all data (not filtered), and filter in the departments helper function

    // in Template.livechatDepartments.onCreated
    this.subscribe('livechat:departments');
    
    // in Template.livechatDepartments.helpers
    departments() {
      const departmentFilter = Template.instance().filter.get().department;
        if (departmentFilter){
          return LivechatDepartment.find({name: departmentFilter }, { sort: { name: -1 } });
        } 
        else {
          return LivechatDepartment.find({}, { sort: { name: -1 } });
        } 
    }
    
  • Solution 2 - Keep departments helper with filter from Solution 1 , but now subscribe twice to livechat:departments

You can reuse the current publish for the filtered list of departments (add back your filtered subscription), and create a new pub/sub channel that publishes all the departments, but only needs to send the name + _id fields used to populate select options.

JeremyK
  • 3,240
  • 1
  • 11
  • 24