Use Case: Smart Worklist Member Custom Functionality

posted Mar 23, 2012, 7:54 PM by Eric Patrick


The Smart Worklist Member panel requires functionality to:
  • Change the priority of items
  • Assign items manually (both Team and User)
  • Put items back into the queue for re-work (uncomplete, unassign)
  • Complete items (only if the user has permissions)
Implementing these changes included:
  • Modifying SmartWorklistMember.Search.xslt to include options for each of these functions
  • Adding Statements to SmartWorklistMember.config to handle these functions
  • Creating a SmartWorklistMember.Popup.xslt to handle prompting the user for information

SmartWorklistMember.Search.xslt Options: Using Popups

These functions are powerful, so I wanted to ensure the user has permissions to execute them, and indeed intends to execute them. To check permissions, I simply wrap the options in the XSLT with a permissions check:

<xsl:if test="security:hasPermission('SmartWorklistMemberReassign')">
<li class="menu-complete" onclick="qbo3.getObject(this).popup('SWLM_Assign', {{ addIds: true, method: 'Reassign' }});">Assign Items</li>

The security:hasPermission is an Xslt Extension call defined in the qbo.Security.Utilities.XsltSecurity class, made available to all QBO 3 XSLTs via the XsltExtension.config with the namespace urn:qbo3-security.

Each option, rather than invoking a statement directly, calls a popup. The qbo.AbstractObject and qbo.Popup javascript classes work closely together, but boil down to this:
  • if a Save button is clicked, a class method is invoked
  • if a Cancel button is clicked, no method is invoked
  • any checkbox values checked in a list of items will be merged with form data from the popup, and passed as data to the class method
For reasinging work, the user needs to select one or more Smart Worklist Member items, and then choose a Team and a User in a popup. Breaking down the snippet of javascript:

qbo3.getObject(this).popup('SWLM_Assign', {{ addIds: true, method: 'Reassign' }})
  • qbo3.AbstractObject.popup method is being called with two parameters: a popup name, and JSON data
  • the key parameter can either be a relative URL to the popup, or (in this case) a shortcut key
  • the shortcut key is defined in Decision.js, and is simply to make coding a popup easier
  • the addIns JSON property is "special", and is used by qbo3.AbstractObject to mesh the IDs a user has checked with the form data being returned by the popup
In the Decision.js, Decision-specific popup shortcuts are defined as follows:

// Define commonly used popups.
if (qbo3 && qbo3.Popups) {
'SWLM_Priority': 'Theme.ashx/Render?Transform=Templates/Decision/SmartWorklistMember.Popup.xslt&Mode=Priority&cache=12000',
'SWLM_Assign': 'Theme.ashx/Render?Transform=Templates/Decision/SmartWorklistMember.Popup.xslt&Mode=Assign&cache=12000'

SmartWorklistMember.config Statements

All of the Smart Worklist Member functionality described here can be achieved using Abstract.config's BulkUpdate, so technically, we don't need any new statements as far as SQL is concerned.  However, these are powerful functions, so I created custom statements for three reasons:

  • Each Statement includes a Permission attribute, so we can restrict these specific permissions to specific roles,
  • Each Statement includes some default Parameters, so we do not need to pass extra information over the wire for most use cases, and
  • Having custom Statement names makes reading the Javascript code easier and clearer to other developers

SmartWorklistMember.Popup.xslt Prompting

There is a standard "Confirmation" XSLT that is reused for options that don't need extra data, like BulkComplete. This is called as follows:

<li class="menu-complete" onclick="qbo3.getObject(this).popup('Confirm', {{ addIds: true, method: 'BulkComplete', Title: 'Are you sure?' }});">Complete Items</li>

The 'Confirm' popup key is defined in qbo.Popups.js, and just renders Templates/Application/Confirm.Popup.xslt.

The Change Priority and Assign options require more user input than a simple confirmation. I could have created two XSLTs, but chose one because the content is short and easily handled (and readable) with an xsl:choose statement.  Thus:
  • Priority: Theme.ashx/Render?Transform=Templates/Decision/SmartWorklistMember.Popup.xslt&Mode=Priority&cache=12000
  • Assign: Theme.ashx/Render?Transform=Templates/Decision/SmartWorklistMember.Popup.xslt&Mode=Assign&cache=12000
Note that when assigning users to a Smart Worklist Item, it's generally a bad idea to display all Person rows; BPO systems have many thousands of active users. Instead, I present the user with a dropdown list of Teams (Collections where SourceObject = 'Person'), and then based on the Team select, a dropdown of Persons (CollectionMembers for the chosen Collection).  The dropdown dependency is handled by:

<select id="PersonCollectionID" name="PersonCollectionID" data-behavior="Dropdown" data-dropdown-options="{{
'url': 'Contact/Collection.ashx/TeamList?output=Json', 
'jsonEval': 'CollectionCollection.CollectionItem', 
'value': 'CollectionID', 
'text': 'Collection' }}" 
onchange="'AssignedPersonID').retrieve('qbo.Dropdown').refresh({{CollectionID: this.value}})
<option value="">-- Team --</option>
<select id="AssignedPersonID" name="AssignedPersonID" data-behavior="Dropdown" data-dropdown-options="{{
 'url': 'Contact/Collection.ashx/MemberList?output=Json', 
 'jsonEval': 'CollectionMemberCollection.CollectionMemberItem', 
 'value': 'SourceObjectID', 
 'text': 'CollectionMember', 
 'refreshOnLoad': false }}">
<option value="">-- User --</option>

Note that:
  • the Team dropdown has an onchange handler to refresh the User dropdown, and
  • the User dropdown has a refreshOnLoad: false option set so that it "waits" to load content until told to do so by the Team dropdown