At BrightGen, we are big fans of Salesforce1, especially for our Sales and Service Management functions - being able to work on leads, opportunities and cases while on the move is vital to ensure we provide the best possible experience to customers and prospects. New leads and cases are assigned to queues, and then picked up by the appropriate Account Executive or Service Management Consultant.
At the time of writing, one of the gaps in the Salesforce1 mobile application is the ability to take ownership of a record. In the main UI, the lead view page has a Change link:
which opens the Change Owner page, allowing a new owner to be selected:
In the Salesforce1 application, the lead owner is a link to the underlying user record:
while when editing the record, the owner field is read-only:
There are a number of ways to solve this problem - my colleague and fellow Salesforce Certified Technical Architect, Chris Eales came up with an admin-friendly solution involving an additional custom field, Update Record publisher action and small trigger. However, when adding functionality to Salesforce1, especially for our internal use, I like to provide a slicker user experience than the configuration tools allow - it requires developer skills to maintain, but those aren’t skills that are in short supply at BrightGen!
My first cut of this (a tactical solution early one morning) was entirely focused on leads, and used an extension controller in conjunction with the standard lead controller, but replicating this across other objects involved cutting and pasting code and markup which is always an indicator that the solution is less than optimal.
My final version follows the principles of DRY, and makes use of a custom component for the heavy lifting. A Visualforce page using the standard controller is still required to create a custom publisher action for the sobject type in question, but this is now reduced to a couple of lines.
The component controller instantiates an sobject based on its type name, using the Schema.SobjectType newSobject() method:
private static sObject createsObject(String typeName) { Schema.SObjectType targetType = Schema.getGlobalDescribe().get(typeName); return (null==targetType?null:targetType.newSObject()); }
A Visualforce remoting method uses dynamic DML to set the owner id on the newly instantiated record:
Id uid=UserInfo.getUserId(); Sobject sobj=createSobject(typeName); if (null!=sobj) { sobj.put('id', recId); sobj.put('OwnerId', UserInfo.getUserId()); upsert sobj; }
On a side note - this wouldn’t have been possible a prior to API version 27, as the ability to set the id field didn’t exist. I could have set it in the createSObject() function call, but I wanted to make my utility method capable of creating an empty sobject.
The Visualforce component that is backed by this controller provides almost all of the markup, outside of the HTML element, to generate the custom publisher action, leaving the containing Visualforce page very little to do:
<apex:page standardController="Lead" applyHtmlTag="false" showheader="false" standardstylesheets="false"> <html> <c:TakeOwnership typeName="{!$ObjectType.Lead.Name}"
typeLabel="{!$ObjectType.Lead.label}" recordId="{!Lead.id}" /> </html> </apex:page>
The component itself is a little more complex, as the custom publisher action can appear not only in the Salesforce1 application, but also in the chatter publisher in the standard UI. As the standard UI doesn’t provide the Submit/Cancel buttons, there’s some JavaScript to render buttons when not in Salesforce1 mode and tie them in to the Visualforce remoting method. There is also JavaScript to refresh the containing page in this scenario, as there is no way in the standard UI to refresh the publisher once an action is complete (not that I’m aware of anyway - if you know of a way to achieve this I’d love to hear about it).
Clicking on the publisher action puts up an Are You Sure page:
Tapping the submit button executes the remote method to change ownership to the current user, and displays an animated status message courtesy of the alertlfy JavaScript library:
The component relies on a few JavaScript libraries - Bootstrap for the UI, alertify as mentioned for the notifications and JQueryBlock to great out the page when a button is tapped.
You can view the source (including unit tests!) at the github repository:
Its also available as an unmanaged package - I’m intending to add more Salesforce1 features into this over time, so check back regularly. The installation link is in the github readme file.
Pretty smooth solution! I implemented something similar as well as SMS messaging from a publisher action a couple weeks ago.
ReplyDelete