Friday, March 18, 2011

Queue-Member Edit Customizations

Using the standard Salesforce Queue edit pages for users can be somewhat tiresome, especially if you need to make mass changes. Not to mention that the amount of page refreshes it requires to edit more than 5 users, takes enough time to make you want to throw your keyboard. So to get around that, making a custom page to stream line the process.


 

In my Org I created a User-List page which shows each user by department, in a sortable list/table(more about this & how to make it here) that allows for easy access to a users contact info. From this table, Manager's/TeamLead's/VP's, can click 'edit' next to a user and get taken to a QueueMember edit page witch shows all Queues and whether or not the user belongs to it. Then I also made it so the Edit part of the page was as easy as a click and the page wouldn't need to be refreshed at all.

What this would entail is a userId passed to the page so we know what User we are talking about. Then it would need to get a list of all Queues and then ones only specific for that user. If they wanted to add the user to the Queue, the Queue Id would need to be passed back to the controller, and the same for removing the user from the Queue. Then we update the page with the new User specific Queues and repeat.

public with sharing class QueueMemberEditCon {

      public string sUserName{get;set;}
      public string sQueueId{get;set;}
      public string sUserId{get;set;}
      
      public List<GroupMember> lstFullGroupMemberList{get{returnQueueMemberHelper.FindGroupIdsFromMembers(sUserId);}set;}
      public List<QueueSobject> lstFullQueueList{get{returnQueueMemberHelper.FindQueueList();}set;}
      
      public Pagereference loadUser()
      {
            sUserId = GlobalHelper.UrlParam('UserId');
            if(GlobalHelper.CheckForNotNull(sUserId))
            {
                  sUserName = QueueMemberHelper.UserName(sUserId);
            }
            return null;
      }
      public pageReference RemoveUserFromQueue()
      {
            sQueueId = GlobalHelper.UrlParam('QueueId');
            sUserId = GlobalHelper.UrlParam('UserId');
            if(GlobalHelper.CheckForNotNull(sQueueId) && GlobalHelper.CheckForNotNull(sUserId))
            {
                  QueueMemberHelper.RemoveUserFromQueue(sQueueId, sUserId);
            }
            return null;
      }
      
      public pageReference AddUserToQueue()
      {
            sQueueId = GlobalHelper.UrlParam('QueueId');
            sUserId = GlobalHelper.UrlParam('UserId');
            if(GlobalHelper.CheckForNotNull(sQueueId) && GlobalHelper.CheckForNotNull(sUserId))
            {
                  QueueMemberHelper.AddUserToQueue(sQueueId, sUserId);
            }
            return null;
      }
}

All the work is done in my helper class, but it still only has a few methods in it. The first one retrieves the entire Queue list for the sObject Case, where as the next one Finds the one that are specific to the UserId that is passed. This could technically be split into two methods, but that's up to you. Then of course there is the RemoveUserFromQueue/AddUserToQueue methods which are void but could be booleans so we can base the next steps on whether or not the method was successful, but I decided against it for now. And finally the UserName method which should explain itself. 

public with sharing class QueueMemberHelper {
      /// <summary>
    /// FINDS LIST OF QUEUES UNDER CASE
    /// </summary>
    /// <returns>LIST OF QUEUES</returns>
      public static List<QueueSobject> FindQueueList()
      {
            QueueSobject[] q = [Select Id, QueueId, Queue.Name From QueueSobject whereSobjectType = 'Case' limit 100];
            return q;
      }
      /// <summary>
    /// FINDS USER IN ALL GROUP MEMEBER ITEMS
    /// </summary>
    /// <param name="sInUserId">USER ID</param>
    /// <returns>LIST OF QUEUES</returns>
      public static List<GroupMember> FindGroupIdsFromMembers(string sInUserId)
      {
            if(GlobalHelper.CheckForNotNull(sInUserId))
            {
                  List<string> sList = new List<string>();
                  List<GroupMember> gList = new List<GroupMember>();                  
                  try
                  {
                        GroupMember[] gm = [Select Id, GroupId, Group.Name, UserOrGroupId FromGroupMember Where UserOrGroupId =:sInUserId limit 100];
                        if(GlobalHelper.CheckForNotNull(gm))
                        {
                              for(GroupMember g : gm)
                              {
                                    if(!GlobalHelper.ContainsItem(g.Group.Name, sList))   
                                    {
                                          gList.add(g);
                                    }
                              }
                              return GlobalHelper.AddItemsToList(gList);
                        }
                  }
                  catch(exception e)
                  {
                        system.debug('Oops... QueueMemberHelper - FindGroupIdsFromMember - Error: ' + e);
                        return null;
                  }
            }
            return null;
      }
      /// <summary>
    /// FINDS USER NAME
    /// </summary>
    /// <param name="sInUserId">USER ID</param>
    /// <returns>USER NAME</returns>
      public static string UserName(string sInUserId)
      {
            try
            {
                  User u = [select Name from User where id=:sInUserId limit 1];
                  return u.Name;
            }
            catch(exception e)
            {
                  system.debug('UserInfoListHelper - UserName - error: '+e);
            }     
            return null;
      }
      /// <summary>
    /// REMOVED USER FROM QUEUE MEMBER
    /// </summary>
    /// <param name="sInQueueId">QUEUE ID</param>
    /// <param name="sInUserId">USER ID</param>
      public static void RemoveUserFromQueue(string sInQueueId, string sInUserId)
      {
            try
            {
                  GroupMember gm = [Select Id, GroupId, UserOrGroupId From GroupMember whereUserOrGroupId =:sInUserId and GroupId =:sInQueueId limit 1];
                  if(gm != null)
                  {
                        try
                        {
                              delete gm;
                        }
                        catch(exception e)
                        {
                              system.debug('Oops... QueueMemberHelper - RemoveUserFromQueue - Error: ' + e);
                        }
                  }
            }
            catch(exception e)
            {
                  system.debug('Oops... QueueMemberHelper - RemoveUserFromQueue - Error: ' + e);
            }
            
      }
      /// <summary>
    /// ADDS USER TO QUEUE MEMBER
    /// </summary>
    /// <param name="sInQueueId">QUEUE ID</param>
    /// <param name="sInUserId">USER ID</param>
      public static void AddUserToQueue(string sInQueueId, string sInUserId)
      {
            GroupMember gm = new GroupMember(
                  GroupId = sInQueueId,
                  UserOrGroupId = sInUserId
            );
            try
            {
                  insert gm;
            }
            catch(exception e)
            {
                  system.debug('Oops... QueueMemberHelper - AddUserToQueue - Error: ' + e);
            }
      }
}

So on the Page I used the jQuery table sorter(more info here), and in the apex:repeat parts, you will see I do some 'ninja' to make sure that it displays the correct info. In the apex:repeat I use rendered="{!IF(q.Queue.Name == u.Group.Name, true, false)}" to ensure that it only shows that they have that Queue if the two lists match. Then I use jQuery to Hide or Show the 'Add' or 'Remove' links based on if that field has content.

<apex:page controller="QueueMemberEditCon" standardStylesheets="false" title="Queue Member Edit"action="{!loadUser}">
<apex:stylesheet value="{!URLFOR($Resource.UserList, '/NewTQC.css')}"/>
<apex:stylesheet value="{!URLFOR($Resource.UserList, '/style.css')}"/>
<script type="text/javascript" language="javascript" src="{!URLFOR($Resource.UserList, '/js/jquery1_4.js')}" ></script>
<script type="text/javascript" language="javascript" src="{!URLFOR($Resource.UserList, '/js/jquery.tablesorter.min.js')}" ></script>
<apex:form >
<div id="pageWrap" style="width:85%; margin:auto;">
<apex:outputPanel id="TicketListWrap" styleClass="Wrap">
      <script language="javascript" type="text/javascript">
            function Loading(b)
            {
                  if(b){
                        $('.loadingIcon').removeClass('hideIt');
                  }else{
                        $('.loadingIcon').addClass('hideIt');
                  }
            }
            function handleMembers()
            {
                  $('.memberCol').each(function(){
                  if($(this).find('.IsMember').text().trim() == 'Remove')
                  {
                        $(this).find('.IsMember').removeClass('hideMe');
                  }else{
                        $(this).find('.NotMemeber').removeClass('hideMe');
                  }
                });
            }
            $(document).ready(function(){
                  $("table").tablesorter({
                    headers: {
                        0: {sorter: 'text'},
                        1: {sorter: 'text'},
                        2: {sorter: 'text'},
                        3: {sorter: 'text'},
                        4: {sorter: 'text'},
                        5: {sorter: 'text'},
                        6: {sorter: 'text'
                    }
                });
                handleMembers();
            });   
      </script>
      <apex:outputpanel id="queueList">
            <div class="clear"></div>
            <div id="newTicketHeader" class="floatL">
                  Showing Queue's for&nbsp;{!sUserName}
            </div>
            <div class="floatR">
                  <apex:outputlink value="/apex/UserInfoList" onClick="Loading(true);">Back to Users</apex:outputlink>
            </div>
            <div class="loadingIcon hideIt"><apex:image id="loadingImage" value="{!URLFOR($Resource.UserList, 'images/loader_24x26.gif')}" width="24" height="26"/></div>
            <div class="clear" ></div>
            <table id="Usertable" class="list tablesorter" cellspacing="1" style="width:85%; margin:auto;">
            <thead class="rich-table-thead">
                  <tr class="headerRow">
                        <th colspan="1" scope="col">Queues</th>
                        <th colspan="1" scope="col">Is Member</th>
                        <th colspan="1" scope="col">Action</th>
                  </tr>
            </thead>
            <tbody>
                  <apex:repeat value="{!lstFullQueueList}" var="q" id="QueueListRepeater">
                  <tr class="dataRow">
                        <td>{!q.Queue.Name}</td>
                        <td>
                              <apex:repeat value="{!lstFullGroupMemberList}" var="u">
                                    <apex:outputpanel rendered="{!IF(q.Queue.Name == u.Group.Name, true, false)}">
                                          Yes
                                    </apex:outputpanel>
                              </apex:repeat>
                        </td>
                        <td class="memberCol">
                              <div class="hideMe IsMember">
                              <apex:repeat value="{!lstFullGroupMemberList}" var="u">
                                    <apex:outputpanel rendered="{!IF(q.Queue.Name == u.Group.Name, true, false)}">
                                          <apex:CommandLink value="Remove"onClick="Loading(true);" action="{!RemoveUserFromQueue}" rerender="TicketListWrap"oncomplete="Loading(false);">
                                                <apex:param name="QueueId" value="{!q.QueueId}"/>
                                          </apex:CommandLink>
                                    </apex:outputpanel>
                              </apex:repeat>
                              </div>
                              <div class="hideMe NotMemeber">
                                    <apex:CommandLink value="Add" onClick="Loading(true);"action="{!AddUserToQueue}" rerender="TicketListWrap" oncomplete="Loading(false);">
                                          <apex:param name="QueueId" value="{!q.QueueId}"/>
                                    </apex:CommandLink>
                              </div>
                        </td>
                  </tr>
                  </apex:repeat>
            </tbody></table>
      </apex:outputpanel>
      </apex:outputpanel>
</div>
</apex:form>
</apex:page>

Questions? 
Twitter: @SalesForceGirl  or Facebook

No comments:

Post a Comment